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,637 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML Export
|
|
3
|
+
*
|
|
4
|
+
* Generates clean, semantic HTML from TipTap editor content.
|
|
5
|
+
* Supports optional styling, class prefixes, and full document wrapping.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Export editor document to HTML
|
|
10
|
+
*
|
|
11
|
+
* @param {Editor} editor - TipTap editor instance
|
|
12
|
+
* @param {Object} options - Export options
|
|
13
|
+
* @returns {string} HTML content
|
|
14
|
+
*/
|
|
15
|
+
export function exportToHTML(editor, options = {}) {
|
|
16
|
+
const {
|
|
17
|
+
includeStyles = true,
|
|
18
|
+
inlineStyles = false,
|
|
19
|
+
classPrefix = "inkpen-",
|
|
20
|
+
embedImages = false,
|
|
21
|
+
includeWrapper = true,
|
|
22
|
+
title = "Document",
|
|
23
|
+
theme = "light"
|
|
24
|
+
} = options
|
|
25
|
+
|
|
26
|
+
// Get raw HTML from editor
|
|
27
|
+
let content = editor.getHTML()
|
|
28
|
+
|
|
29
|
+
// Add class prefixes if specified
|
|
30
|
+
if (classPrefix && classPrefix !== "inkpen-") {
|
|
31
|
+
content = addClassPrefix(content, classPrefix)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Embed images as base64 if requested
|
|
35
|
+
if (embedImages) {
|
|
36
|
+
content = embedImagesAsBase64(content)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Wrap in full HTML document
|
|
40
|
+
if (includeWrapper) {
|
|
41
|
+
return wrapInDocument(content, {
|
|
42
|
+
title,
|
|
43
|
+
includeStyles,
|
|
44
|
+
inlineStyles,
|
|
45
|
+
classPrefix,
|
|
46
|
+
theme
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Return content with optional style tag
|
|
51
|
+
if (includeStyles && inlineStyles) {
|
|
52
|
+
return `<style>${getExportStyles(classPrefix)}</style>\n${content}`
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return content
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Wrap content in a full HTML document
|
|
60
|
+
*/
|
|
61
|
+
function wrapInDocument(content, options) {
|
|
62
|
+
const { title, includeStyles, inlineStyles, classPrefix, theme } = options
|
|
63
|
+
|
|
64
|
+
let styleBlock = ""
|
|
65
|
+
if (includeStyles) {
|
|
66
|
+
if (inlineStyles) {
|
|
67
|
+
styleBlock = ` <style>\n${getExportStyles(classPrefix, 4)}\n </style>`
|
|
68
|
+
} else {
|
|
69
|
+
styleBlock = ` <link rel="stylesheet" href="inkpen-export.css">`
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return `<!DOCTYPE html>
|
|
74
|
+
<html lang="en" data-theme="${theme}">
|
|
75
|
+
<head>
|
|
76
|
+
<meta charset="UTF-8">
|
|
77
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
78
|
+
<title>${escapeHtml(title)}</title>
|
|
79
|
+
${styleBlock}
|
|
80
|
+
</head>
|
|
81
|
+
<body>
|
|
82
|
+
<article class="${classPrefix}document">
|
|
83
|
+
${indentContent(content, 4)}
|
|
84
|
+
</article>
|
|
85
|
+
</body>
|
|
86
|
+
</html>`
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Get export styles
|
|
91
|
+
*/
|
|
92
|
+
function getExportStyles(prefix = "inkpen-", indent = 0) {
|
|
93
|
+
const pad = " ".repeat(indent)
|
|
94
|
+
|
|
95
|
+
const styles = `
|
|
96
|
+
/* Base document styles */
|
|
97
|
+
.${prefix}document {
|
|
98
|
+
max-width: 680px;
|
|
99
|
+
margin: 0 auto;
|
|
100
|
+
padding: 2rem;
|
|
101
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
102
|
+
font-size: 16px;
|
|
103
|
+
line-height: 1.6;
|
|
104
|
+
color: #1a1a1a;
|
|
105
|
+
background: #ffffff;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Typography */
|
|
109
|
+
.${prefix}document h1 {
|
|
110
|
+
font-size: 2rem;
|
|
111
|
+
font-weight: 700;
|
|
112
|
+
margin: 2rem 0 1rem;
|
|
113
|
+
line-height: 1.2;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.${prefix}document h2 {
|
|
117
|
+
font-size: 1.5rem;
|
|
118
|
+
font-weight: 600;
|
|
119
|
+
margin: 1.75rem 0 0.75rem;
|
|
120
|
+
line-height: 1.3;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.${prefix}document h3 {
|
|
124
|
+
font-size: 1.25rem;
|
|
125
|
+
font-weight: 600;
|
|
126
|
+
margin: 1.5rem 0 0.5rem;
|
|
127
|
+
line-height: 1.4;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.${prefix}document h4 {
|
|
131
|
+
font-size: 1rem;
|
|
132
|
+
font-weight: 600;
|
|
133
|
+
margin: 1.25rem 0 0.5rem;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.${prefix}document p {
|
|
137
|
+
margin: 0 0 1rem;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.${prefix}document a {
|
|
141
|
+
color: #2563eb;
|
|
142
|
+
text-decoration: underline;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.${prefix}document a:hover {
|
|
146
|
+
color: #1d4ed8;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* Lists */
|
|
150
|
+
.${prefix}document ul,
|
|
151
|
+
.${prefix}document ol {
|
|
152
|
+
margin: 0 0 1rem;
|
|
153
|
+
padding-left: 1.5rem;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.${prefix}document li {
|
|
157
|
+
margin: 0.25rem 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.${prefix}document li > ul,
|
|
161
|
+
.${prefix}document li > ol {
|
|
162
|
+
margin: 0.25rem 0;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* Task list */
|
|
166
|
+
.${prefix}document ul[data-type="taskList"] {
|
|
167
|
+
list-style: none;
|
|
168
|
+
padding-left: 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.${prefix}document ul[data-type="taskList"] li {
|
|
172
|
+
display: flex;
|
|
173
|
+
align-items: flex-start;
|
|
174
|
+
gap: 0.5rem;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.${prefix}document ul[data-type="taskList"] input[type="checkbox"] {
|
|
178
|
+
margin-top: 0.25rem;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/* Blockquote */
|
|
182
|
+
.${prefix}document blockquote {
|
|
183
|
+
margin: 1rem 0;
|
|
184
|
+
padding: 0.75rem 1rem;
|
|
185
|
+
border-left: 3px solid #e5e7eb;
|
|
186
|
+
color: #4b5563;
|
|
187
|
+
background: #f9fafb;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.${prefix}document blockquote p:last-child {
|
|
191
|
+
margin-bottom: 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* Code */
|
|
195
|
+
.${prefix}document code {
|
|
196
|
+
background: #f3f4f6;
|
|
197
|
+
padding: 0.125rem 0.375rem;
|
|
198
|
+
border-radius: 0.25rem;
|
|
199
|
+
font-size: 0.875em;
|
|
200
|
+
font-family: 'SF Mono', SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.${prefix}document pre {
|
|
204
|
+
background: #1f2937;
|
|
205
|
+
color: #f9fafb;
|
|
206
|
+
padding: 1rem;
|
|
207
|
+
border-radius: 0.5rem;
|
|
208
|
+
overflow-x: auto;
|
|
209
|
+
margin: 1rem 0;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.${prefix}document pre code {
|
|
213
|
+
background: transparent;
|
|
214
|
+
padding: 0;
|
|
215
|
+
font-size: 0.875rem;
|
|
216
|
+
color: inherit;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* Horizontal rule */
|
|
220
|
+
.${prefix}document hr {
|
|
221
|
+
border: none;
|
|
222
|
+
border-top: 1px solid #e5e7eb;
|
|
223
|
+
margin: 2rem 0;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/* Images */
|
|
227
|
+
.${prefix}document img {
|
|
228
|
+
max-width: 100%;
|
|
229
|
+
height: auto;
|
|
230
|
+
border-radius: 0.5rem;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.${prefix}document figure {
|
|
234
|
+
margin: 1.5rem 0;
|
|
235
|
+
text-align: center;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.${prefix}document figcaption {
|
|
239
|
+
margin-top: 0.5rem;
|
|
240
|
+
font-size: 0.875rem;
|
|
241
|
+
color: #6b7280;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/* Tables */
|
|
245
|
+
.${prefix}document table {
|
|
246
|
+
width: 100%;
|
|
247
|
+
border-collapse: collapse;
|
|
248
|
+
margin: 1rem 0;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.${prefix}document th,
|
|
252
|
+
.${prefix}document td {
|
|
253
|
+
border: 1px solid #e5e7eb;
|
|
254
|
+
padding: 0.5rem 0.75rem;
|
|
255
|
+
text-align: left;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.${prefix}document th {
|
|
259
|
+
background: #f9fafb;
|
|
260
|
+
font-weight: 600;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.${prefix}document tr:nth-child(even) td {
|
|
264
|
+
background: #fafafa;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Callouts */
|
|
268
|
+
.${prefix}callout {
|
|
269
|
+
padding: 1rem;
|
|
270
|
+
margin: 1rem 0;
|
|
271
|
+
border-radius: 0.5rem;
|
|
272
|
+
border-left: 4px solid;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.${prefix}callout--info {
|
|
276
|
+
background: #eff6ff;
|
|
277
|
+
border-color: #3b82f6;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.${prefix}callout--warning {
|
|
281
|
+
background: #fffbeb;
|
|
282
|
+
border-color: #f59e0b;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.${prefix}callout--tip {
|
|
286
|
+
background: #f0fdf4;
|
|
287
|
+
border-color: #22c55e;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.${prefix}callout--note {
|
|
291
|
+
background: #f5f5f5;
|
|
292
|
+
border-color: #737373;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.${prefix}callout--success {
|
|
296
|
+
background: #f0fdf4;
|
|
297
|
+
border-color: #22c55e;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.${prefix}callout--error {
|
|
301
|
+
background: #fef2f2;
|
|
302
|
+
border-color: #ef4444;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/* Toggle/Details */
|
|
306
|
+
.${prefix}document details {
|
|
307
|
+
margin: 1rem 0;
|
|
308
|
+
border: 1px solid #e5e7eb;
|
|
309
|
+
border-radius: 0.5rem;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.${prefix}document summary {
|
|
313
|
+
padding: 0.75rem 1rem;
|
|
314
|
+
cursor: pointer;
|
|
315
|
+
font-weight: 500;
|
|
316
|
+
background: #f9fafb;
|
|
317
|
+
border-radius: 0.5rem 0.5rem 0 0;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.${prefix}document details[open] summary {
|
|
321
|
+
border-bottom: 1px solid #e5e7eb;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.${prefix}document details > *:not(summary) {
|
|
325
|
+
padding: 1rem;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/* Columns */
|
|
329
|
+
.${prefix}columns {
|
|
330
|
+
display: grid;
|
|
331
|
+
gap: 1.5rem;
|
|
332
|
+
margin: 1rem 0;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.${prefix}columns--2 { grid-template-columns: repeat(2, 1fr); }
|
|
336
|
+
.${prefix}columns--3 { grid-template-columns: repeat(3, 1fr); }
|
|
337
|
+
.${prefix}columns--4 { grid-template-columns: repeat(4, 1fr); }
|
|
338
|
+
|
|
339
|
+
@media (max-width: 640px) {
|
|
340
|
+
.${prefix}columns {
|
|
341
|
+
grid-template-columns: 1fr !important;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/* File attachment */
|
|
346
|
+
.${prefix}file {
|
|
347
|
+
display: flex;
|
|
348
|
+
align-items: center;
|
|
349
|
+
gap: 0.75rem;
|
|
350
|
+
padding: 0.75rem 1rem;
|
|
351
|
+
background: #f9fafb;
|
|
352
|
+
border: 1px solid #e5e7eb;
|
|
353
|
+
border-radius: 0.5rem;
|
|
354
|
+
margin: 1rem 0;
|
|
355
|
+
text-decoration: none;
|
|
356
|
+
color: inherit;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.${prefix}file:hover {
|
|
360
|
+
background: #f3f4f6;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.${prefix}file__icon {
|
|
364
|
+
font-size: 1.5rem;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.${prefix}file__info {
|
|
368
|
+
flex: 1;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.${prefix}file__name {
|
|
372
|
+
font-weight: 500;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.${prefix}file__size {
|
|
376
|
+
font-size: 0.75rem;
|
|
377
|
+
color: #6b7280;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/* Embed */
|
|
381
|
+
.${prefix}embed {
|
|
382
|
+
margin: 1.5rem 0;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.${prefix}embed iframe {
|
|
386
|
+
width: 100%;
|
|
387
|
+
border: none;
|
|
388
|
+
border-radius: 0.5rem;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/* Table of Contents */
|
|
392
|
+
.${prefix}toc {
|
|
393
|
+
padding: 1rem 1.5rem;
|
|
394
|
+
background: #f9fafb;
|
|
395
|
+
border: 1px solid #e5e7eb;
|
|
396
|
+
border-radius: 0.5rem;
|
|
397
|
+
margin: 1.5rem 0;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.${prefix}toc__title {
|
|
401
|
+
font-weight: 600;
|
|
402
|
+
font-size: 0.875rem;
|
|
403
|
+
text-transform: uppercase;
|
|
404
|
+
letter-spacing: 0.05em;
|
|
405
|
+
color: #6b7280;
|
|
406
|
+
margin-bottom: 0.75rem;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.${prefix}toc__list {
|
|
410
|
+
margin: 0;
|
|
411
|
+
padding-left: 1.25rem;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
.${prefix}toc__item {
|
|
415
|
+
padding: 0.25rem 0;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
.${prefix}toc__item a {
|
|
419
|
+
color: inherit;
|
|
420
|
+
text-decoration: none;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.${prefix}toc__item a:hover {
|
|
424
|
+
color: #2563eb;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* Database */
|
|
428
|
+
.${prefix}database {
|
|
429
|
+
margin: 1.5rem 0;
|
|
430
|
+
border: 1px solid #e5e7eb;
|
|
431
|
+
border-radius: 0.5rem;
|
|
432
|
+
overflow: hidden;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.${prefix}database__header {
|
|
436
|
+
padding: 0.75rem 1rem;
|
|
437
|
+
background: #f9fafb;
|
|
438
|
+
border-bottom: 1px solid #e5e7eb;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.${prefix}database__title {
|
|
442
|
+
font-weight: 600;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/* Marks */
|
|
446
|
+
.${prefix}document mark,
|
|
447
|
+
.${prefix}highlight {
|
|
448
|
+
background: #fef08a;
|
|
449
|
+
padding: 0.125rem 0;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.${prefix}document u {
|
|
453
|
+
text-decoration: underline;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.${prefix}document s {
|
|
457
|
+
text-decoration: line-through;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
.${prefix}document sub {
|
|
461
|
+
font-size: 0.75em;
|
|
462
|
+
vertical-align: sub;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.${prefix}document sup {
|
|
466
|
+
font-size: 0.75em;
|
|
467
|
+
vertical-align: super;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/* Dark mode */
|
|
471
|
+
@media (prefers-color-scheme: dark) {
|
|
472
|
+
[data-theme="auto"] .${prefix}document {
|
|
473
|
+
background: #111827;
|
|
474
|
+
color: #f9fafb;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
[data-theme="auto"] .${prefix}document a {
|
|
478
|
+
color: #60a5fa;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
[data-theme="auto"] .${prefix}document blockquote {
|
|
482
|
+
background: #1f2937;
|
|
483
|
+
border-color: #374151;
|
|
484
|
+
color: #9ca3af;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
[data-theme="auto"] .${prefix}document code {
|
|
488
|
+
background: #374151;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
[data-theme="auto"] .${prefix}document th,
|
|
492
|
+
[data-theme="auto"] .${prefix}document summary {
|
|
493
|
+
background: #1f2937;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
[data-theme="auto"] .${prefix}document th,
|
|
497
|
+
[data-theme="auto"] .${prefix}document td {
|
|
498
|
+
border-color: #374151;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
[data-theme="dark"] .${prefix}document {
|
|
503
|
+
background: #111827;
|
|
504
|
+
color: #f9fafb;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
[data-theme="dark"] .${prefix}document a {
|
|
508
|
+
color: #60a5fa;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
[data-theme="dark"] .${prefix}document blockquote {
|
|
512
|
+
background: #1f2937;
|
|
513
|
+
border-color: #374151;
|
|
514
|
+
color: #9ca3af;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
[data-theme="dark"] .${prefix}document code {
|
|
518
|
+
background: #374151;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/* Print styles */
|
|
522
|
+
@media print {
|
|
523
|
+
.${prefix}document {
|
|
524
|
+
max-width: none;
|
|
525
|
+
padding: 0;
|
|
526
|
+
font-size: 12pt;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.${prefix}document a {
|
|
530
|
+
color: inherit;
|
|
531
|
+
text-decoration: underline;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.${prefix}document pre {
|
|
535
|
+
white-space: pre-wrap;
|
|
536
|
+
word-wrap: break-word;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.${prefix}document img {
|
|
540
|
+
max-width: 100%;
|
|
541
|
+
page-break-inside: avoid;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
.${prefix}document table {
|
|
545
|
+
page-break-inside: avoid;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
.${prefix}document h1, .${prefix}document h2, .${prefix}document h3 {
|
|
549
|
+
page-break-after: avoid;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
`
|
|
553
|
+
|
|
554
|
+
// Add indent to each line
|
|
555
|
+
return styles
|
|
556
|
+
.split("\n")
|
|
557
|
+
.map(line => pad + line)
|
|
558
|
+
.join("\n")
|
|
559
|
+
.trim()
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Add class prefix to HTML content
|
|
564
|
+
*/
|
|
565
|
+
function addClassPrefix(html, prefix) {
|
|
566
|
+
// Replace inkpen- with custom prefix
|
|
567
|
+
return html.replace(/inkpen-/g, prefix)
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Embed images as base64
|
|
572
|
+
*/
|
|
573
|
+
function embedImagesAsBase64(html) {
|
|
574
|
+
// This would require async image loading in practice
|
|
575
|
+
// For now, return unchanged (implement with canvas if needed)
|
|
576
|
+
return html
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Indent content for prettier output
|
|
581
|
+
*/
|
|
582
|
+
function indentContent(content, spaces) {
|
|
583
|
+
const pad = " ".repeat(spaces)
|
|
584
|
+
return content
|
|
585
|
+
.split("\n")
|
|
586
|
+
.map(line => line.trim() ? pad + line : "")
|
|
587
|
+
.join("\n")
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Escape HTML entities
|
|
592
|
+
*/
|
|
593
|
+
function escapeHtml(text) {
|
|
594
|
+
const map = {
|
|
595
|
+
"&": "&",
|
|
596
|
+
"<": "<",
|
|
597
|
+
">": ">",
|
|
598
|
+
'"': """,
|
|
599
|
+
"'": "'"
|
|
600
|
+
}
|
|
601
|
+
return text.replace(/[&<>"']/g, char => map[char])
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Download HTML as file
|
|
606
|
+
*/
|
|
607
|
+
export function downloadHTML(content, filename = "document.html") {
|
|
608
|
+
const blob = new Blob([content], { type: "text/html;charset=utf-8" })
|
|
609
|
+
const url = URL.createObjectURL(blob)
|
|
610
|
+
const link = document.createElement("a")
|
|
611
|
+
link.href = url
|
|
612
|
+
link.download = filename
|
|
613
|
+
document.body.appendChild(link)
|
|
614
|
+
link.click()
|
|
615
|
+
document.body.removeChild(link)
|
|
616
|
+
URL.revokeObjectURL(url)
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Copy HTML to clipboard
|
|
621
|
+
*/
|
|
622
|
+
export async function copyHTMLToClipboard(content) {
|
|
623
|
+
try {
|
|
624
|
+
await navigator.clipboard.writeText(content)
|
|
625
|
+
return true
|
|
626
|
+
} catch (err) {
|
|
627
|
+
console.error("Failed to copy HTML:", err)
|
|
628
|
+
return false
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Get standalone stylesheet content
|
|
634
|
+
*/
|
|
635
|
+
export function getExportStylesheet(prefix = "inkpen-") {
|
|
636
|
+
return getExportStyles(prefix, 0)
|
|
637
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inkpen Export Module
|
|
3
|
+
*
|
|
4
|
+
* Provides export functionality for Markdown, HTML, and PDF formats.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Markdown export/import
|
|
8
|
+
export {
|
|
9
|
+
exportToMarkdown,
|
|
10
|
+
importFromMarkdown,
|
|
11
|
+
downloadMarkdown,
|
|
12
|
+
copyMarkdownToClipboard
|
|
13
|
+
} from "inkpen/export/markdown"
|
|
14
|
+
|
|
15
|
+
// HTML export
|
|
16
|
+
export {
|
|
17
|
+
exportToHTML,
|
|
18
|
+
downloadHTML,
|
|
19
|
+
copyHTMLToClipboard,
|
|
20
|
+
getExportStylesheet
|
|
21
|
+
} from "inkpen/export/html"
|
|
22
|
+
|
|
23
|
+
// PDF export
|
|
24
|
+
export {
|
|
25
|
+
exportToPDF,
|
|
26
|
+
loadHtml2Pdf,
|
|
27
|
+
isPDFExportAvailable,
|
|
28
|
+
getPageSizes,
|
|
29
|
+
getDefaultPDFOptions
|
|
30
|
+
} from "inkpen/export/pdf"
|