inkpen 0.7.1
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.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.rubocop.yml +8 -0
- data/.yardopts +11 -0
- data/CLAUDE.md +141 -0
- data/README.md +409 -0
- data/Rakefile +19 -0
- data/app/assets/javascripts/inkpen/controllers/editor_controller.js +2050 -0
- data/app/assets/javascripts/inkpen/controllers/sticky_toolbar_controller.js +667 -0
- data/app/assets/javascripts/inkpen/controllers/toolbar_controller.js +693 -0
- data/app/assets/javascripts/inkpen/export/html.js +637 -0
- data/app/assets/javascripts/inkpen/export/index.js +30 -0
- data/app/assets/javascripts/inkpen/export/markdown.js +697 -0
- data/app/assets/javascripts/inkpen/export/pdf.js +372 -0
- data/app/assets/javascripts/inkpen/extensions/advanced_table.js +640 -0
- data/app/assets/javascripts/inkpen/extensions/block_commands.js +300 -0
- data/app/assets/javascripts/inkpen/extensions/block_gutter.js +338 -0
- data/app/assets/javascripts/inkpen/extensions/callout.js +303 -0
- data/app/assets/javascripts/inkpen/extensions/columns.js +403 -0
- data/app/assets/javascripts/inkpen/extensions/database.js +990 -0
- data/app/assets/javascripts/inkpen/extensions/document_section.js +352 -0
- data/app/assets/javascripts/inkpen/extensions/drag_handle.js +407 -0
- data/app/assets/javascripts/inkpen/extensions/embed.js +629 -0
- data/app/assets/javascripts/inkpen/extensions/enhanced_image.js +566 -0
- data/app/assets/javascripts/inkpen/extensions/export_commands.js +271 -0
- data/app/assets/javascripts/inkpen/extensions/file_attachment.js +593 -0
- data/app/assets/javascripts/inkpen/extensions/inkpen_table/index.js +58 -0
- data/app/assets/javascripts/inkpen/extensions/inkpen_table/inkpen_table.js +638 -0
- data/app/assets/javascripts/inkpen/extensions/inkpen_table/inkpen_table_cell.js +100 -0
- data/app/assets/javascripts/inkpen/extensions/inkpen_table/inkpen_table_header.js +100 -0
- data/app/assets/javascripts/inkpen/extensions/inkpen_table/table_constants.js +152 -0
- data/app/assets/javascripts/inkpen/extensions/inkpen_table/table_helpers.js +254 -0
- data/app/assets/javascripts/inkpen/extensions/inkpen_table/table_menu.js +282 -0
- data/app/assets/javascripts/inkpen/extensions/preformatted.js +239 -0
- data/app/assets/javascripts/inkpen/extensions/section.js +281 -0
- data/app/assets/javascripts/inkpen/extensions/section_title.js +126 -0
- data/app/assets/javascripts/inkpen/extensions/slash_commands.js +439 -0
- data/app/assets/javascripts/inkpen/extensions/table_of_contents.js +474 -0
- data/app/assets/javascripts/inkpen/extensions/toggle_block.js +332 -0
- data/app/assets/javascripts/inkpen/index.js +87 -0
- data/app/assets/stylesheets/inkpen/advanced_table.css +514 -0
- data/app/assets/stylesheets/inkpen/animations.css +626 -0
- data/app/assets/stylesheets/inkpen/block_gutter.css +265 -0
- data/app/assets/stylesheets/inkpen/callout.css +359 -0
- data/app/assets/stylesheets/inkpen/columns.css +314 -0
- data/app/assets/stylesheets/inkpen/database.css +658 -0
- data/app/assets/stylesheets/inkpen/document_section.css +305 -0
- data/app/assets/stylesheets/inkpen/drag_drop.css +220 -0
- data/app/assets/stylesheets/inkpen/editor.css +652 -0
- data/app/assets/stylesheets/inkpen/embed.css +468 -0
- data/app/assets/stylesheets/inkpen/enhanced_image.css +453 -0
- data/app/assets/stylesheets/inkpen/export.css +499 -0
- data/app/assets/stylesheets/inkpen/file_attachment.css +347 -0
- data/app/assets/stylesheets/inkpen/footnotes.css +136 -0
- data/app/assets/stylesheets/inkpen/inkpen_table.css +608 -0
- data/app/assets/stylesheets/inkpen/preformatted.css +215 -0
- data/app/assets/stylesheets/inkpen/search_replace.css +58 -0
- data/app/assets/stylesheets/inkpen/section.css +236 -0
- data/app/assets/stylesheets/inkpen/slash_menu.css +252 -0
- data/app/assets/stylesheets/inkpen/sticky_toolbar.css +314 -0
- data/app/assets/stylesheets/inkpen/toc.css +386 -0
- data/app/assets/stylesheets/inkpen/toggle.css +260 -0
- data/app/helpers/inkpen/editor_helper.rb +114 -0
- data/app/views/inkpen/_editor.html.erb +139 -0
- data/config/importmap.rb +170 -0
- data/docs/.DS_Store +0 -0
- data/docs/CHANGELOG.md +571 -0
- data/docs/FEATURES.md +436 -0
- data/docs/ROADMAP.md +3029 -0
- data/docs/VISION.md +235 -0
- data/docs/extensions/INKPEN_TABLE.md +482 -0
- data/docs/thinking/CORRECTED_NO_VUE.md +756 -0
- data/docs/thinking/EXECUTIVE_SUMMARY.md +403 -0
- data/docs/thinking/INKPEN_CODE_SAMPLES.md +1479 -0
- data/docs/thinking/INKPEN_MASTER_GUIDE.md +891 -0
- data/docs/thinking/README_START_HERE.md +341 -0
- data/lib/inkpen/configuration.rb +175 -0
- data/lib/inkpen/editor.rb +204 -0
- data/lib/inkpen/engine.rb +32 -0
- data/lib/inkpen/extensions/base.rb +109 -0
- data/lib/inkpen/extensions/code_block_syntax.rb +177 -0
- data/lib/inkpen/extensions/document_section.rb +111 -0
- data/lib/inkpen/extensions/forced_document.rb +183 -0
- data/lib/inkpen/extensions/mention.rb +155 -0
- data/lib/inkpen/extensions/preformatted.rb +111 -0
- data/lib/inkpen/extensions/section.rb +139 -0
- data/lib/inkpen/extensions/slash_commands.rb +100 -0
- data/lib/inkpen/extensions/table.rb +182 -0
- data/lib/inkpen/extensions/task_list.rb +145 -0
- data/lib/inkpen/sticky_toolbar.rb +157 -0
- data/lib/inkpen/toolbar.rb +145 -0
- data/lib/inkpen/version.rb +5 -0
- data/lib/inkpen.rb +101 -0
- data/sig/inkpen.rbs +4 -0
- metadata +165 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { Extension } from "@tiptap/core"
|
|
2
|
+
import {
|
|
3
|
+
exportToMarkdown,
|
|
4
|
+
downloadMarkdown,
|
|
5
|
+
copyMarkdownToClipboard,
|
|
6
|
+
exportToHTML,
|
|
7
|
+
downloadHTML,
|
|
8
|
+
copyHTMLToClipboard,
|
|
9
|
+
exportToPDF
|
|
10
|
+
} from "inkpen/export"
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Export Commands Extension for TipTap
|
|
14
|
+
*
|
|
15
|
+
* Adds keyboard shortcuts and commands for exporting editor content
|
|
16
|
+
* to Markdown, HTML, and PDF formats.
|
|
17
|
+
*
|
|
18
|
+
* Follows Fizzy patterns:
|
|
19
|
+
* - Section comments for organization
|
|
20
|
+
* - Clean command API
|
|
21
|
+
* - Event-driven callbacks
|
|
22
|
+
*
|
|
23
|
+
* Keyboard Shortcuts:
|
|
24
|
+
* - Cmd+Alt+M: Download as Markdown
|
|
25
|
+
* - Cmd+Alt+H: Download as HTML
|
|
26
|
+
* - Cmd+Alt+P: Download as PDF
|
|
27
|
+
* - Cmd+Alt+C: Copy as Markdown
|
|
28
|
+
* - Cmd+Alt+Shift+C: Copy as HTML
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* editor.commands.downloadMarkdown()
|
|
32
|
+
* editor.commands.downloadHTML({ includeStyles: true })
|
|
33
|
+
* editor.commands.downloadPDF({ pageSize: 'letter' })
|
|
34
|
+
*
|
|
35
|
+
* @since 0.7.0
|
|
36
|
+
*/
|
|
37
|
+
export const ExportCommands = Extension.create({
|
|
38
|
+
name: "exportCommands",
|
|
39
|
+
|
|
40
|
+
// Options
|
|
41
|
+
|
|
42
|
+
addOptions() {
|
|
43
|
+
return {
|
|
44
|
+
/**
|
|
45
|
+
* Default filename for Markdown export (without extension)
|
|
46
|
+
*/
|
|
47
|
+
defaultFilename: "document",
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Default options for Markdown export
|
|
51
|
+
*/
|
|
52
|
+
markdownOptions: {},
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Default options for HTML export
|
|
56
|
+
*/
|
|
57
|
+
htmlOptions: {
|
|
58
|
+
includeStyles: true,
|
|
59
|
+
inlineStyles: true,
|
|
60
|
+
includeWrapper: true
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Default options for PDF export
|
|
65
|
+
*/
|
|
66
|
+
pdfOptions: {
|
|
67
|
+
pageSize: "a4",
|
|
68
|
+
orientation: "portrait",
|
|
69
|
+
margins: { top: 20, right: 20, bottom: 20, left: 20 }
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Callback when export succeeds
|
|
74
|
+
* @param {string} format - Export format (markdown, html, pdf)
|
|
75
|
+
* @param {string} action - Action performed (download, copy)
|
|
76
|
+
*/
|
|
77
|
+
onExportSuccess: null,
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Callback when export fails
|
|
81
|
+
* @param {string} format - Export format
|
|
82
|
+
* @param {Error} error - Error that occurred
|
|
83
|
+
*/
|
|
84
|
+
onExportError: null
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
// Commands
|
|
89
|
+
|
|
90
|
+
addCommands() {
|
|
91
|
+
return {
|
|
92
|
+
/**
|
|
93
|
+
* Export and download as Markdown file
|
|
94
|
+
* @param {Object} options - Export options
|
|
95
|
+
* @param {string} options.filename - Filename for download
|
|
96
|
+
* @param {boolean} options.includeFrontmatter - Include YAML frontmatter
|
|
97
|
+
* @param {Object} options.frontmatter - Frontmatter data
|
|
98
|
+
*/
|
|
99
|
+
downloadMarkdown: (options = {}) => ({ editor }) => {
|
|
100
|
+
try {
|
|
101
|
+
const filename = options.filename || `${this.options.defaultFilename}.md`
|
|
102
|
+
const exportOptions = { ...this.options.markdownOptions, ...options }
|
|
103
|
+
const markdown = exportToMarkdown(editor.getJSON(), exportOptions)
|
|
104
|
+
downloadMarkdown(markdown, filename)
|
|
105
|
+
this._notifySuccess("markdown", "download")
|
|
106
|
+
return true
|
|
107
|
+
} catch (error) {
|
|
108
|
+
this._notifyError("markdown", error)
|
|
109
|
+
return false
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Copy editor content as Markdown to clipboard
|
|
115
|
+
* @param {Object} options - Export options
|
|
116
|
+
*/
|
|
117
|
+
copyMarkdown: (options = {}) => ({ editor }) => {
|
|
118
|
+
try {
|
|
119
|
+
const exportOptions = { ...this.options.markdownOptions, ...options }
|
|
120
|
+
const markdown = exportToMarkdown(editor.getJSON(), exportOptions)
|
|
121
|
+
copyMarkdownToClipboard(markdown).then(success => {
|
|
122
|
+
if (success) {
|
|
123
|
+
this._notifySuccess("markdown", "copy")
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
return true
|
|
127
|
+
} catch (error) {
|
|
128
|
+
this._notifyError("markdown", error)
|
|
129
|
+
return false
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Export and download as HTML file
|
|
135
|
+
* @param {Object} options - Export options
|
|
136
|
+
* @param {string} options.filename - Filename for download
|
|
137
|
+
* @param {boolean} options.includeStyles - Include CSS styles
|
|
138
|
+
* @param {boolean} options.inlineStyles - Embed styles in document
|
|
139
|
+
* @param {string} options.classPrefix - CSS class prefix
|
|
140
|
+
* @param {string} options.theme - Theme (light, dark, auto)
|
|
141
|
+
*/
|
|
142
|
+
downloadHTML: (options = {}) => ({ editor }) => {
|
|
143
|
+
try {
|
|
144
|
+
const filename = options.filename || `${this.options.defaultFilename}.html`
|
|
145
|
+
const exportOptions = { ...this.options.htmlOptions, ...options }
|
|
146
|
+
const html = exportToHTML(editor, exportOptions)
|
|
147
|
+
downloadHTML(html, filename)
|
|
148
|
+
this._notifySuccess("html", "download")
|
|
149
|
+
return true
|
|
150
|
+
} catch (error) {
|
|
151
|
+
this._notifyError("html", error)
|
|
152
|
+
return false
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Copy editor content as HTML to clipboard
|
|
158
|
+
* @param {Object} options - Export options
|
|
159
|
+
*/
|
|
160
|
+
copyHTML: (options = {}) => ({ editor }) => {
|
|
161
|
+
try {
|
|
162
|
+
const exportOptions = {
|
|
163
|
+
...this.options.htmlOptions,
|
|
164
|
+
...options,
|
|
165
|
+
includeWrapper: false,
|
|
166
|
+
includeStyles: false
|
|
167
|
+
}
|
|
168
|
+
const html = exportToHTML(editor, exportOptions)
|
|
169
|
+
copyHTMLToClipboard(html).then(success => {
|
|
170
|
+
if (success) {
|
|
171
|
+
this._notifySuccess("html", "copy")
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
return true
|
|
175
|
+
} catch (error) {
|
|
176
|
+
this._notifyError("html", error)
|
|
177
|
+
return false
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Export and download as PDF file
|
|
183
|
+
* @param {Object} options - Export options
|
|
184
|
+
* @param {string} options.filename - Filename for download
|
|
185
|
+
* @param {string} options.pageSize - Page size (a4, letter, legal)
|
|
186
|
+
* @param {string} options.orientation - Orientation (portrait, landscape)
|
|
187
|
+
* @param {Object} options.margins - Margins in mm
|
|
188
|
+
*/
|
|
189
|
+
downloadPDF: (options = {}) => ({ editor }) => {
|
|
190
|
+
try {
|
|
191
|
+
const filename = options.filename || `${this.options.defaultFilename}.pdf`
|
|
192
|
+
const exportOptions = { ...this.options.pdfOptions, ...options, filename }
|
|
193
|
+
exportToPDF(editor, exportOptions).then(() => {
|
|
194
|
+
this._notifySuccess("pdf", "download")
|
|
195
|
+
}).catch(error => {
|
|
196
|
+
this._notifyError("pdf", error)
|
|
197
|
+
})
|
|
198
|
+
return true
|
|
199
|
+
} catch (error) {
|
|
200
|
+
this._notifyError("pdf", error)
|
|
201
|
+
return false
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Get Markdown string without downloading
|
|
207
|
+
* @param {Object} options - Export options
|
|
208
|
+
* @returns {string} Markdown content
|
|
209
|
+
*/
|
|
210
|
+
getMarkdown: (options = {}) => ({ editor }) => {
|
|
211
|
+
const exportOptions = { ...this.options.markdownOptions, ...options }
|
|
212
|
+
return exportToMarkdown(editor.getJSON(), exportOptions)
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get HTML string without downloading
|
|
217
|
+
* @param {Object} options - Export options
|
|
218
|
+
* @returns {string} HTML content
|
|
219
|
+
*/
|
|
220
|
+
getHTML: (options = {}) => ({ editor }) => {
|
|
221
|
+
const exportOptions = { ...this.options.htmlOptions, ...options }
|
|
222
|
+
return exportToHTML(editor, exportOptions)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
// Keyboard Shortcuts
|
|
228
|
+
|
|
229
|
+
addKeyboardShortcuts() {
|
|
230
|
+
return {
|
|
231
|
+
// Download shortcuts (Mod-Alt)
|
|
232
|
+
"Mod-Alt-m": () => this.editor.commands.downloadMarkdown(),
|
|
233
|
+
"Mod-Alt-h": () => this.editor.commands.downloadHTML(),
|
|
234
|
+
"Mod-Alt-p": () => this.editor.commands.downloadPDF(),
|
|
235
|
+
|
|
236
|
+
// Copy shortcuts (Mod-Alt-Shift)
|
|
237
|
+
"Mod-Alt-Shift-m": () => this.editor.commands.copyMarkdown(),
|
|
238
|
+
"Mod-Alt-Shift-h": () => this.editor.commands.copyHTML()
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
// Helpers (underscore prefix for internal methods in TipTap extensions)
|
|
243
|
+
|
|
244
|
+
_notifySuccess(format, action) {
|
|
245
|
+
if (this.options.onExportSuccess) {
|
|
246
|
+
this.options.onExportSuccess(format, action)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Dispatch DOM event for external listeners
|
|
250
|
+
const event = new CustomEvent("inkpen:export-success", {
|
|
251
|
+
bubbles: true,
|
|
252
|
+
detail: { format, action }
|
|
253
|
+
})
|
|
254
|
+
this.editor.view.dom.dispatchEvent(event)
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
_notifyError(format, error) {
|
|
258
|
+
console.error(`Export to ${format} failed:`, error)
|
|
259
|
+
|
|
260
|
+
if (this.options.onExportError) {
|
|
261
|
+
this.options.onExportError(format, error)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Dispatch DOM event for external listeners
|
|
265
|
+
const event = new CustomEvent("inkpen:export-error", {
|
|
266
|
+
bubbles: true,
|
|
267
|
+
detail: { format, error }
|
|
268
|
+
})
|
|
269
|
+
this.editor.view.dom.dispatchEvent(event)
|
|
270
|
+
}
|
|
271
|
+
})
|