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.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.rubocop.yml +8 -0
  4. data/.yardopts +11 -0
  5. data/CLAUDE.md +141 -0
  6. data/README.md +409 -0
  7. data/Rakefile +19 -0
  8. data/app/assets/javascripts/inkpen/controllers/editor_controller.js +2050 -0
  9. data/app/assets/javascripts/inkpen/controllers/sticky_toolbar_controller.js +667 -0
  10. data/app/assets/javascripts/inkpen/controllers/toolbar_controller.js +693 -0
  11. data/app/assets/javascripts/inkpen/export/html.js +637 -0
  12. data/app/assets/javascripts/inkpen/export/index.js +30 -0
  13. data/app/assets/javascripts/inkpen/export/markdown.js +697 -0
  14. data/app/assets/javascripts/inkpen/export/pdf.js +372 -0
  15. data/app/assets/javascripts/inkpen/extensions/advanced_table.js +640 -0
  16. data/app/assets/javascripts/inkpen/extensions/block_commands.js +300 -0
  17. data/app/assets/javascripts/inkpen/extensions/block_gutter.js +338 -0
  18. data/app/assets/javascripts/inkpen/extensions/callout.js +303 -0
  19. data/app/assets/javascripts/inkpen/extensions/columns.js +403 -0
  20. data/app/assets/javascripts/inkpen/extensions/database.js +990 -0
  21. data/app/assets/javascripts/inkpen/extensions/document_section.js +352 -0
  22. data/app/assets/javascripts/inkpen/extensions/drag_handle.js +407 -0
  23. data/app/assets/javascripts/inkpen/extensions/embed.js +629 -0
  24. data/app/assets/javascripts/inkpen/extensions/enhanced_image.js +566 -0
  25. data/app/assets/javascripts/inkpen/extensions/export_commands.js +271 -0
  26. data/app/assets/javascripts/inkpen/extensions/file_attachment.js +593 -0
  27. data/app/assets/javascripts/inkpen/extensions/inkpen_table/index.js +58 -0
  28. data/app/assets/javascripts/inkpen/extensions/inkpen_table/inkpen_table.js +638 -0
  29. data/app/assets/javascripts/inkpen/extensions/inkpen_table/inkpen_table_cell.js +100 -0
  30. data/app/assets/javascripts/inkpen/extensions/inkpen_table/inkpen_table_header.js +100 -0
  31. data/app/assets/javascripts/inkpen/extensions/inkpen_table/table_constants.js +152 -0
  32. data/app/assets/javascripts/inkpen/extensions/inkpen_table/table_helpers.js +254 -0
  33. data/app/assets/javascripts/inkpen/extensions/inkpen_table/table_menu.js +282 -0
  34. data/app/assets/javascripts/inkpen/extensions/preformatted.js +239 -0
  35. data/app/assets/javascripts/inkpen/extensions/section.js +281 -0
  36. data/app/assets/javascripts/inkpen/extensions/section_title.js +126 -0
  37. data/app/assets/javascripts/inkpen/extensions/slash_commands.js +439 -0
  38. data/app/assets/javascripts/inkpen/extensions/table_of_contents.js +474 -0
  39. data/app/assets/javascripts/inkpen/extensions/toggle_block.js +332 -0
  40. data/app/assets/javascripts/inkpen/index.js +87 -0
  41. data/app/assets/stylesheets/inkpen/advanced_table.css +514 -0
  42. data/app/assets/stylesheets/inkpen/animations.css +626 -0
  43. data/app/assets/stylesheets/inkpen/block_gutter.css +265 -0
  44. data/app/assets/stylesheets/inkpen/callout.css +359 -0
  45. data/app/assets/stylesheets/inkpen/columns.css +314 -0
  46. data/app/assets/stylesheets/inkpen/database.css +658 -0
  47. data/app/assets/stylesheets/inkpen/document_section.css +305 -0
  48. data/app/assets/stylesheets/inkpen/drag_drop.css +220 -0
  49. data/app/assets/stylesheets/inkpen/editor.css +652 -0
  50. data/app/assets/stylesheets/inkpen/embed.css +468 -0
  51. data/app/assets/stylesheets/inkpen/enhanced_image.css +453 -0
  52. data/app/assets/stylesheets/inkpen/export.css +499 -0
  53. data/app/assets/stylesheets/inkpen/file_attachment.css +347 -0
  54. data/app/assets/stylesheets/inkpen/footnotes.css +136 -0
  55. data/app/assets/stylesheets/inkpen/inkpen_table.css +608 -0
  56. data/app/assets/stylesheets/inkpen/preformatted.css +215 -0
  57. data/app/assets/stylesheets/inkpen/search_replace.css +58 -0
  58. data/app/assets/stylesheets/inkpen/section.css +236 -0
  59. data/app/assets/stylesheets/inkpen/slash_menu.css +252 -0
  60. data/app/assets/stylesheets/inkpen/sticky_toolbar.css +314 -0
  61. data/app/assets/stylesheets/inkpen/toc.css +386 -0
  62. data/app/assets/stylesheets/inkpen/toggle.css +260 -0
  63. data/app/helpers/inkpen/editor_helper.rb +114 -0
  64. data/app/views/inkpen/_editor.html.erb +139 -0
  65. data/config/importmap.rb +170 -0
  66. data/docs/.DS_Store +0 -0
  67. data/docs/CHANGELOG.md +571 -0
  68. data/docs/FEATURES.md +436 -0
  69. data/docs/ROADMAP.md +3029 -0
  70. data/docs/VISION.md +235 -0
  71. data/docs/extensions/INKPEN_TABLE.md +482 -0
  72. data/docs/thinking/CORRECTED_NO_VUE.md +756 -0
  73. data/docs/thinking/EXECUTIVE_SUMMARY.md +403 -0
  74. data/docs/thinking/INKPEN_CODE_SAMPLES.md +1479 -0
  75. data/docs/thinking/INKPEN_MASTER_GUIDE.md +891 -0
  76. data/docs/thinking/README_START_HERE.md +341 -0
  77. data/lib/inkpen/configuration.rb +175 -0
  78. data/lib/inkpen/editor.rb +204 -0
  79. data/lib/inkpen/engine.rb +32 -0
  80. data/lib/inkpen/extensions/base.rb +109 -0
  81. data/lib/inkpen/extensions/code_block_syntax.rb +177 -0
  82. data/lib/inkpen/extensions/document_section.rb +111 -0
  83. data/lib/inkpen/extensions/forced_document.rb +183 -0
  84. data/lib/inkpen/extensions/mention.rb +155 -0
  85. data/lib/inkpen/extensions/preformatted.rb +111 -0
  86. data/lib/inkpen/extensions/section.rb +139 -0
  87. data/lib/inkpen/extensions/slash_commands.rb +100 -0
  88. data/lib/inkpen/extensions/table.rb +182 -0
  89. data/lib/inkpen/extensions/task_list.rb +145 -0
  90. data/lib/inkpen/sticky_toolbar.rb +157 -0
  91. data/lib/inkpen/toolbar.rb +145 -0
  92. data/lib/inkpen/version.rb +5 -0
  93. data/lib/inkpen.rb +101 -0
  94. data/sig/inkpen.rbs +4 -0
  95. metadata +165 -0
@@ -0,0 +1,347 @@
1
+ /**
2
+ * File Attachment Extension Styles
3
+ *
4
+ * Styles for file upload cards with icons, progress, and download.
5
+ *
6
+ * @since 0.5.0
7
+ */
8
+
9
+ /* ==========================================================================
10
+ File Container
11
+ ========================================================================== */
12
+
13
+ .inkpen-file {
14
+ display: block;
15
+ margin: 1rem 0;
16
+ border-radius: var(--inkpen-radius, 0.375rem);
17
+ overflow: hidden;
18
+ transition: box-shadow var(--inkpen-animation-fast, 100ms) ease-out;
19
+ }
20
+
21
+ .inkpen-file:hover {
22
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
23
+ }
24
+
25
+ .inkpen-file.is-selected {
26
+ box-shadow: 0 0 0 2px var(--inkpen-color-primary, #3b82f6);
27
+ }
28
+
29
+ /* ==========================================================================
30
+ File Link (complete state)
31
+ ========================================================================== */
32
+
33
+ .inkpen-file__link {
34
+ display: flex;
35
+ align-items: center;
36
+ gap: 0.75rem;
37
+ padding: 0.875rem 1rem;
38
+ background: var(--inkpen-color-border, #f3f4f6);
39
+ border: 1px solid var(--inkpen-color-border, #e5e7eb);
40
+ border-radius: var(--inkpen-radius, 0.375rem);
41
+ text-decoration: none;
42
+ color: inherit;
43
+ transition: background var(--inkpen-animation-fast, 100ms) ease-out,
44
+ border-color var(--inkpen-animation-fast, 100ms) ease-out;
45
+ }
46
+
47
+ .inkpen-file__link:hover {
48
+ background: var(--inkpen-color-selection, rgba(59, 130, 246, 0.08));
49
+ border-color: var(--inkpen-color-primary, #3b82f6);
50
+ }
51
+
52
+ /* ==========================================================================
53
+ File Icon
54
+ ========================================================================== */
55
+
56
+ .inkpen-file__icon {
57
+ flex-shrink: 0;
58
+ display: flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ width: 40px;
62
+ height: 40px;
63
+ font-size: 1.5rem;
64
+ background: var(--inkpen-color-background, #ffffff);
65
+ border-radius: 8px;
66
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
67
+ }
68
+
69
+ /* ==========================================================================
70
+ File Info
71
+ ========================================================================== */
72
+
73
+ .inkpen-file__info {
74
+ flex: 1;
75
+ min-width: 0;
76
+ display: flex;
77
+ flex-direction: column;
78
+ gap: 0.125rem;
79
+ }
80
+
81
+ .inkpen-file__name {
82
+ font-weight: 500;
83
+ font-size: 0.9375rem;
84
+ color: var(--inkpen-color-text, #1a1a1a);
85
+ white-space: nowrap;
86
+ overflow: hidden;
87
+ text-overflow: ellipsis;
88
+ }
89
+
90
+ .inkpen-file__meta {
91
+ font-size: 0.8125rem;
92
+ color: var(--inkpen-color-text-muted, #6b7280);
93
+ }
94
+
95
+ .inkpen-file__meta--error {
96
+ color: #dc2626;
97
+ }
98
+
99
+ /* ==========================================================================
100
+ Download Button
101
+ ========================================================================== */
102
+
103
+ .inkpen-file__download {
104
+ flex-shrink: 0;
105
+ display: flex;
106
+ align-items: center;
107
+ justify-content: center;
108
+ width: 36px;
109
+ height: 36px;
110
+ background: var(--inkpen-color-primary, #3b82f6);
111
+ color: white;
112
+ border-radius: 8px;
113
+ opacity: 0;
114
+ transform: translateX(4px);
115
+ transition: opacity var(--inkpen-animation-fast, 100ms) ease-out,
116
+ transform var(--inkpen-animation-fast, 100ms) ease-out,
117
+ background var(--inkpen-animation-fast, 100ms) ease-out;
118
+ }
119
+
120
+ .inkpen-file__link:hover .inkpen-file__download {
121
+ opacity: 1;
122
+ transform: translateX(0);
123
+ }
124
+
125
+ .inkpen-file__download:hover {
126
+ background: var(--inkpen-color-primary-dark, #2563eb);
127
+ }
128
+
129
+ .inkpen-file__download svg {
130
+ width: 18px;
131
+ height: 18px;
132
+ }
133
+
134
+ /* ==========================================================================
135
+ Uploading State
136
+ ========================================================================== */
137
+
138
+ .inkpen-file__uploading {
139
+ display: flex;
140
+ align-items: center;
141
+ gap: 0.75rem;
142
+ padding: 0.875rem 1rem;
143
+ background: var(--inkpen-color-border, #f3f4f6);
144
+ border: 1px solid var(--inkpen-color-border, #e5e7eb);
145
+ border-radius: var(--inkpen-radius, 0.375rem);
146
+ position: relative;
147
+ }
148
+
149
+ .inkpen-file__progress {
150
+ position: absolute;
151
+ bottom: 0;
152
+ left: 0;
153
+ right: 0;
154
+ height: 3px;
155
+ background: var(--inkpen-color-border, #e5e7eb);
156
+ border-radius: 0 0 var(--inkpen-radius, 0.375rem) var(--inkpen-radius, 0.375rem);
157
+ overflow: hidden;
158
+ }
159
+
160
+ .inkpen-file__progress-bar {
161
+ height: 100%;
162
+ background: var(--inkpen-color-primary, #3b82f6);
163
+ border-radius: 0 0 0 var(--inkpen-radius, 0.375rem);
164
+ transition: width 150ms ease-out;
165
+ }
166
+
167
+ /* Animated gradient for progress bar */
168
+ .inkpen-file__progress-bar::after {
169
+ content: "";
170
+ position: absolute;
171
+ inset: 0;
172
+ background: linear-gradient(
173
+ 90deg,
174
+ transparent,
175
+ rgba(255, 255, 255, 0.3),
176
+ transparent
177
+ );
178
+ animation: inkpen-file-progress-shine 1.5s ease-in-out infinite;
179
+ }
180
+
181
+ @keyframes inkpen-file-progress-shine {
182
+ 0% {
183
+ transform: translateX(-100%);
184
+ }
185
+ 100% {
186
+ transform: translateX(100%);
187
+ }
188
+ }
189
+
190
+ /* ==========================================================================
191
+ Error State
192
+ ========================================================================== */
193
+
194
+ .inkpen-file__error {
195
+ display: flex;
196
+ align-items: center;
197
+ gap: 0.75rem;
198
+ padding: 0.875rem 1rem;
199
+ background: rgba(220, 38, 38, 0.05);
200
+ border: 1px solid rgba(220, 38, 38, 0.2);
201
+ border-radius: var(--inkpen-radius, 0.375rem);
202
+ }
203
+
204
+ .inkpen-file__retry,
205
+ .inkpen-file__remove {
206
+ flex-shrink: 0;
207
+ display: flex;
208
+ align-items: center;
209
+ justify-content: center;
210
+ width: 28px;
211
+ height: 28px;
212
+ padding: 0;
213
+ background: transparent;
214
+ border: 1px solid var(--inkpen-color-border, #e5e7eb);
215
+ border-radius: 6px;
216
+ color: var(--inkpen-color-text-muted, #6b7280);
217
+ cursor: pointer;
218
+ font-size: 1rem;
219
+ transition: background var(--inkpen-animation-fast, 100ms) ease-out,
220
+ border-color var(--inkpen-animation-fast, 100ms) ease-out,
221
+ color var(--inkpen-animation-fast, 100ms) ease-out;
222
+ }
223
+
224
+ .inkpen-file__retry:hover {
225
+ background: var(--inkpen-color-selection, rgba(59, 130, 246, 0.1));
226
+ border-color: var(--inkpen-color-primary, #3b82f6);
227
+ color: var(--inkpen-color-primary, #3b82f6);
228
+ }
229
+
230
+ .inkpen-file__remove:hover {
231
+ background: rgba(220, 38, 38, 0.1);
232
+ border-color: #dc2626;
233
+ color: #dc2626;
234
+ }
235
+
236
+ /* ==========================================================================
237
+ Dark Mode
238
+ ========================================================================== */
239
+
240
+ [data-theme="dark"],
241
+ .dark {
242
+ .inkpen-file__link {
243
+ background: rgba(255, 255, 255, 0.05);
244
+ border-color: rgba(255, 255, 255, 0.1);
245
+ }
246
+
247
+ .inkpen-file__link:hover {
248
+ background: rgba(59, 130, 246, 0.15);
249
+ border-color: var(--inkpen-color-primary, #3b82f6);
250
+ }
251
+
252
+ .inkpen-file__icon {
253
+ background: rgba(255, 255, 255, 0.1);
254
+ }
255
+
256
+ .inkpen-file__uploading {
257
+ background: rgba(255, 255, 255, 0.05);
258
+ border-color: rgba(255, 255, 255, 0.1);
259
+ }
260
+
261
+ .inkpen-file__error {
262
+ background: rgba(220, 38, 38, 0.1);
263
+ border-color: rgba(220, 38, 38, 0.3);
264
+ }
265
+ }
266
+
267
+ /* ==========================================================================
268
+ Mobile Optimizations
269
+ ========================================================================== */
270
+
271
+ @media (hover: none) and (pointer: coarse) {
272
+ /* Always show download button on touch devices */
273
+ .inkpen-file__download {
274
+ opacity: 1;
275
+ transform: translateX(0);
276
+ }
277
+
278
+ /* Larger touch targets */
279
+ .inkpen-file__link {
280
+ padding: 1rem;
281
+ }
282
+
283
+ .inkpen-file__icon {
284
+ width: 48px;
285
+ height: 48px;
286
+ font-size: 1.75rem;
287
+ }
288
+
289
+ .inkpen-file__download {
290
+ width: 44px;
291
+ height: 44px;
292
+ }
293
+
294
+ .inkpen-file__retry,
295
+ .inkpen-file__remove {
296
+ width: 36px;
297
+ height: 36px;
298
+ }
299
+ }
300
+
301
+ /* Small screens */
302
+ @media (max-width: 480px) {
303
+ .inkpen-file__name {
304
+ font-size: 0.875rem;
305
+ }
306
+
307
+ .inkpen-file__meta {
308
+ font-size: 0.75rem;
309
+ }
310
+ }
311
+
312
+ /* ==========================================================================
313
+ Reduced Motion
314
+ ========================================================================== */
315
+
316
+ @media (prefers-reduced-motion: reduce) {
317
+ .inkpen-file,
318
+ .inkpen-file__link,
319
+ .inkpen-file__download,
320
+ .inkpen-file__progress-bar {
321
+ transition: none;
322
+ }
323
+
324
+ .inkpen-file__progress-bar::after {
325
+ animation: none;
326
+ }
327
+ }
328
+
329
+ /* ==========================================================================
330
+ Print Styles
331
+ ========================================================================== */
332
+
333
+ @media print {
334
+ .inkpen-file__link {
335
+ background: none;
336
+ border: 1px solid #ccc;
337
+ }
338
+
339
+ .inkpen-file__download {
340
+ display: none;
341
+ }
342
+
343
+ .inkpen-file__uploading,
344
+ .inkpen-file__error {
345
+ display: none;
346
+ }
347
+ }
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Footnotes Styles for Inkpen Editor
3
+ *
4
+ * Academic-style footnotes with inline references.
5
+ *
6
+ * @since 0.8.0
7
+ */
8
+
9
+ /* ==========================================================================
10
+ CSS Custom Properties
11
+ ========================================================================== */
12
+
13
+ :root {
14
+ --inkpen-footnote-color: var(--inkpen-color-primary, #3b82f6);
15
+ --inkpen-footnote-border: #e5e7eb;
16
+ --inkpen-footnote-bg: #f9fafb;
17
+ --inkpen-footnote-text: #6b7280;
18
+ }
19
+
20
+ /* Dark mode */
21
+ [data-theme="dark"],
22
+ .dark {
23
+ --inkpen-footnote-border: #374151;
24
+ --inkpen-footnote-bg: #1f2937;
25
+ --inkpen-footnote-text: #9ca3af;
26
+ }
27
+
28
+ /* ==========================================================================
29
+ Footnote Reference (inline superscript)
30
+ ========================================================================== */
31
+
32
+ .inkpen-footnote-ref,
33
+ [data-type="footnoteReference"] {
34
+ color: var(--inkpen-footnote-color);
35
+ font-size: 0.75em;
36
+ vertical-align: super;
37
+ text-decoration: none;
38
+ cursor: pointer;
39
+ font-weight: 600;
40
+ padding: 0 2px;
41
+ border-radius: 2px;
42
+ transition: background-color 150ms ease;
43
+ }
44
+
45
+ .inkpen-footnote-ref:hover,
46
+ [data-type="footnoteReference"]:hover {
47
+ background-color: rgba(59, 130, 246, 0.1);
48
+ text-decoration: underline;
49
+ }
50
+
51
+ /* ==========================================================================
52
+ Footnotes Container (at bottom of document)
53
+ ========================================================================== */
54
+
55
+ .inkpen-footnotes,
56
+ ol.footnotes,
57
+ [data-type="footnotes"] {
58
+ margin-top: 2rem;
59
+ padding-top: 1.5rem;
60
+ border-top: 1px solid var(--inkpen-footnote-border);
61
+ font-size: 0.875rem;
62
+ color: var(--inkpen-footnote-text);
63
+ }
64
+
65
+ .inkpen-footnotes:empty,
66
+ ol.footnotes:empty,
67
+ [data-type="footnotes"]:empty {
68
+ display: none;
69
+ }
70
+
71
+ /* ==========================================================================
72
+ Individual Footnote
73
+ ========================================================================== */
74
+
75
+ .inkpen-footnote,
76
+ li.footnote,
77
+ [data-type="footnote"] {
78
+ margin-bottom: 0.75rem;
79
+ padding-left: 0.5rem;
80
+ line-height: 1.5;
81
+ }
82
+
83
+ .inkpen-footnote:last-child,
84
+ li.footnote:last-child,
85
+ [data-type="footnote"]:last-child {
86
+ margin-bottom: 0;
87
+ }
88
+
89
+ /* Footnote number */
90
+ .inkpen-footnote::marker,
91
+ li.footnote::marker {
92
+ color: var(--inkpen-footnote-color);
93
+ font-weight: 600;
94
+ }
95
+
96
+ /* Back reference link */
97
+ .inkpen-footnote-backref {
98
+ color: var(--inkpen-footnote-color);
99
+ text-decoration: none;
100
+ margin-left: 0.25rem;
101
+ font-size: 0.875em;
102
+ }
103
+
104
+ .inkpen-footnote-backref:hover {
105
+ text-decoration: underline;
106
+ }
107
+
108
+ /* ==========================================================================
109
+ Focus States
110
+ ========================================================================== */
111
+
112
+ .inkpen-footnote:focus-within,
113
+ [data-type="footnote"]:focus-within {
114
+ background-color: var(--inkpen-footnote-bg);
115
+ border-radius: 4px;
116
+ outline: 2px solid var(--inkpen-footnote-color);
117
+ outline-offset: 2px;
118
+ }
119
+
120
+ /* ==========================================================================
121
+ Print Styles
122
+ ========================================================================== */
123
+
124
+ @media print {
125
+ .inkpen-footnotes,
126
+ ol.footnotes,
127
+ [data-type="footnotes"] {
128
+ border-top: 1px solid #000;
129
+ page-break-inside: avoid;
130
+ }
131
+
132
+ .inkpen-footnote-ref,
133
+ [data-type="footnoteReference"] {
134
+ color: #000;
135
+ }
136
+ }