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,468 @@
1
+ /**
2
+ * Social Embed Extension Styles
3
+ *
4
+ * Styles for embedded content from various platforms.
5
+ *
6
+ * @since 0.5.0
7
+ */
8
+
9
+ /* ==========================================================================
10
+ Embed Container
11
+ ========================================================================== */
12
+
13
+ .inkpen-embed {
14
+ margin: 1.5rem 0;
15
+ border-radius: var(--inkpen-radius, 0.375rem);
16
+ overflow: hidden;
17
+ }
18
+
19
+ .inkpen-embed.is-selected {
20
+ box-shadow: 0 0 0 2px var(--inkpen-color-primary, #3b82f6);
21
+ }
22
+
23
+ /* ==========================================================================
24
+ Embed Wrapper (iframe container)
25
+ ========================================================================== */
26
+
27
+ .inkpen-embed__wrapper {
28
+ position: relative;
29
+ width: 100%;
30
+ background: var(--inkpen-color-border, #f3f4f6);
31
+ border-radius: var(--inkpen-radius, 0.375rem);
32
+ overflow: hidden;
33
+ }
34
+
35
+ .inkpen-embed__wrapper iframe {
36
+ position: absolute;
37
+ top: 0;
38
+ left: 0;
39
+ width: 100%;
40
+ height: 100%;
41
+ border: none;
42
+ }
43
+
44
+ /* Fixed aspect ratio embeds */
45
+ .inkpen-embed__wrapper[style*="aspect-ratio"] {
46
+ position: relative;
47
+ }
48
+
49
+ .inkpen-embed__wrapper[style*="aspect-ratio"] iframe {
50
+ position: absolute;
51
+ top: 0;
52
+ left: 0;
53
+ width: 100%;
54
+ height: 100%;
55
+ }
56
+
57
+ /* Fixed height embeds (Spotify) */
58
+ .inkpen-embed__wrapper[style*="height"] iframe {
59
+ position: relative;
60
+ width: 100%;
61
+ }
62
+
63
+ /* Widget embeds (Twitter, Instagram) */
64
+ .inkpen-embed__wrapper--widget {
65
+ min-height: 200px;
66
+ display: flex;
67
+ justify-content: center;
68
+ background: transparent;
69
+ }
70
+
71
+ .inkpen-embed__wrapper--widget .twitter-tweet,
72
+ .inkpen-embed__wrapper--widget .instagram-media {
73
+ margin: 0 auto !important;
74
+ }
75
+
76
+ /* Gist embed */
77
+ .inkpen-embed__wrapper--script {
78
+ background: transparent;
79
+ }
80
+
81
+ .inkpen-embed__gist-frame {
82
+ width: 100%;
83
+ min-height: 100px;
84
+ border: none;
85
+ }
86
+
87
+ /* ==========================================================================
88
+ Privacy Placeholder
89
+ ========================================================================== */
90
+
91
+ .inkpen-embed__placeholder {
92
+ display: flex;
93
+ flex-direction: column;
94
+ align-items: center;
95
+ justify-content: center;
96
+ gap: 1rem;
97
+ padding: 2.5rem 1.5rem;
98
+ background: linear-gradient(
99
+ 135deg,
100
+ var(--inkpen-color-border, #f3f4f6) 0%,
101
+ var(--inkpen-color-background, #ffffff) 100%
102
+ );
103
+ border: 1px solid var(--inkpen-color-border, #e5e7eb);
104
+ border-radius: var(--inkpen-radius, 0.375rem);
105
+ text-align: center;
106
+ }
107
+
108
+ .inkpen-embed__placeholder-icon {
109
+ display: flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ width: 56px;
113
+ height: 56px;
114
+ font-size: 1.75rem;
115
+ background: var(--provider-color, #6b7280);
116
+ color: white;
117
+ border-radius: 12px;
118
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
119
+ }
120
+
121
+ .inkpen-embed__placeholder-info {
122
+ display: flex;
123
+ flex-direction: column;
124
+ gap: 0.25rem;
125
+ }
126
+
127
+ .inkpen-embed__placeholder-name {
128
+ font-weight: 600;
129
+ font-size: 1rem;
130
+ color: var(--inkpen-color-text, #1a1a1a);
131
+ }
132
+
133
+ .inkpen-embed__placeholder-url {
134
+ font-size: 0.8125rem;
135
+ color: var(--inkpen-color-text-muted, #6b7280);
136
+ }
137
+
138
+ .inkpen-embed__load-btn {
139
+ padding: 0.625rem 1.25rem;
140
+ background: var(--provider-color, var(--inkpen-color-primary, #3b82f6));
141
+ color: white;
142
+ border: none;
143
+ border-radius: 9999px;
144
+ font-size: 0.875rem;
145
+ font-weight: 500;
146
+ cursor: pointer;
147
+ transition: transform var(--inkpen-animation-fast, 100ms) ease-out,
148
+ box-shadow var(--inkpen-animation-fast, 100ms) ease-out;
149
+ }
150
+
151
+ .inkpen-embed__load-btn:hover {
152
+ transform: translateY(-1px);
153
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
154
+ }
155
+
156
+ .inkpen-embed__load-btn:active {
157
+ transform: translateY(0);
158
+ }
159
+
160
+ /* ==========================================================================
161
+ Error State
162
+ ========================================================================== */
163
+
164
+ .inkpen-embed__error {
165
+ display: flex;
166
+ align-items: center;
167
+ gap: 0.75rem;
168
+ padding: 1rem 1.25rem;
169
+ background: rgba(220, 38, 38, 0.05);
170
+ border: 1px solid rgba(220, 38, 38, 0.2);
171
+ border-radius: var(--inkpen-radius, 0.375rem);
172
+ }
173
+
174
+ .inkpen-embed__error-icon {
175
+ font-size: 1.25rem;
176
+ }
177
+
178
+ .inkpen-embed__error-text {
179
+ flex: 1;
180
+ font-size: 0.875rem;
181
+ color: #dc2626;
182
+ }
183
+
184
+ .inkpen-embed__remove {
185
+ display: flex;
186
+ align-items: center;
187
+ justify-content: center;
188
+ width: 28px;
189
+ height: 28px;
190
+ padding: 0;
191
+ background: transparent;
192
+ border: 1px solid rgba(220, 38, 38, 0.2);
193
+ border-radius: 6px;
194
+ color: #dc2626;
195
+ font-size: 1.25rem;
196
+ cursor: pointer;
197
+ transition: background var(--inkpen-animation-fast, 100ms) ease-out;
198
+ }
199
+
200
+ .inkpen-embed__remove:hover {
201
+ background: rgba(220, 38, 38, 0.1);
202
+ }
203
+
204
+ /* ==========================================================================
205
+ Link Card (fallback for unknown URLs)
206
+ ========================================================================== */
207
+
208
+ .inkpen-link-card {
209
+ display: flex;
210
+ overflow: hidden;
211
+ background: var(--inkpen-color-background, #ffffff);
212
+ border: 1px solid var(--inkpen-color-border, #e5e7eb);
213
+ border-radius: var(--inkpen-radius, 0.375rem);
214
+ text-decoration: none;
215
+ color: inherit;
216
+ transition: border-color var(--inkpen-animation-fast, 100ms) ease-out,
217
+ box-shadow var(--inkpen-animation-fast, 100ms) ease-out;
218
+ }
219
+
220
+ .inkpen-link-card:hover {
221
+ border-color: var(--inkpen-color-primary, #3b82f6);
222
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
223
+ }
224
+
225
+ .inkpen-link-card__image {
226
+ flex-shrink: 0;
227
+ width: 140px;
228
+ height: 100px;
229
+ object-fit: cover;
230
+ background: var(--inkpen-color-border, #f3f4f6);
231
+ }
232
+
233
+ .inkpen-link-card__content {
234
+ flex: 1;
235
+ display: flex;
236
+ flex-direction: column;
237
+ gap: 0.375rem;
238
+ padding: 0.875rem 1rem;
239
+ min-width: 0;
240
+ }
241
+
242
+ .inkpen-link-card__title {
243
+ font-weight: 500;
244
+ font-size: 0.9375rem;
245
+ color: var(--inkpen-color-text, #1a1a1a);
246
+ display: -webkit-box;
247
+ -webkit-line-clamp: 1;
248
+ -webkit-box-orient: vertical;
249
+ overflow: hidden;
250
+ }
251
+
252
+ .inkpen-link-card__description {
253
+ font-size: 0.8125rem;
254
+ color: var(--inkpen-color-text-muted, #6b7280);
255
+ display: -webkit-box;
256
+ -webkit-line-clamp: 2;
257
+ -webkit-box-orient: vertical;
258
+ overflow: hidden;
259
+ line-height: 1.4;
260
+ }
261
+
262
+ .inkpen-link-card__domain {
263
+ display: flex;
264
+ align-items: center;
265
+ gap: 0.375rem;
266
+ font-size: 0.75rem;
267
+ color: var(--inkpen-color-text-muted, #6b7280);
268
+ margin-top: auto;
269
+ }
270
+
271
+ .inkpen-link-card__domain svg {
272
+ opacity: 0.6;
273
+ }
274
+
275
+ /* ==========================================================================
276
+ Provider-specific styles
277
+ ========================================================================== */
278
+
279
+ /* YouTube */
280
+ .inkpen-embed[data-provider="youtube"] .inkpen-embed__wrapper {
281
+ aspect-ratio: 16/9;
282
+ }
283
+
284
+ /* Vimeo */
285
+ .inkpen-embed[data-provider="vimeo"] .inkpen-embed__wrapper {
286
+ aspect-ratio: 16/9;
287
+ }
288
+
289
+ /* Loom */
290
+ .inkpen-embed[data-provider="loom"] .inkpen-embed__wrapper {
291
+ aspect-ratio: 16/9;
292
+ }
293
+
294
+ /* Figma */
295
+ .inkpen-embed[data-provider="figma"] .inkpen-embed__wrapper {
296
+ aspect-ratio: 16/9;
297
+ min-height: 450px;
298
+ }
299
+
300
+ /* TikTok */
301
+ .inkpen-embed[data-provider="tiktok"] .inkpen-embed__wrapper {
302
+ max-width: 325px;
303
+ margin: 0 auto;
304
+ }
305
+
306
+ /* Spotify */
307
+ .inkpen-embed[data-provider="spotify"] .inkpen-embed__wrapper {
308
+ height: 352px;
309
+ border-radius: 12px;
310
+ }
311
+
312
+ /* CodePen */
313
+ .inkpen-embed[data-provider="codepen"] .inkpen-embed__wrapper {
314
+ aspect-ratio: 16/9;
315
+ min-height: 300px;
316
+ }
317
+
318
+ /* ==========================================================================
319
+ Dark Mode
320
+ ========================================================================== */
321
+
322
+ [data-theme="dark"],
323
+ .dark {
324
+ .inkpen-embed__placeholder {
325
+ background: linear-gradient(
326
+ 135deg,
327
+ rgba(255, 255, 255, 0.05) 0%,
328
+ rgba(255, 255, 255, 0.02) 100%
329
+ );
330
+ border-color: rgba(255, 255, 255, 0.1);
331
+ }
332
+
333
+ .inkpen-embed__wrapper {
334
+ background: rgba(255, 255, 255, 0.05);
335
+ }
336
+
337
+ .inkpen-link-card {
338
+ background: rgba(255, 255, 255, 0.02);
339
+ border-color: rgba(255, 255, 255, 0.1);
340
+ }
341
+
342
+ .inkpen-link-card:hover {
343
+ border-color: var(--inkpen-color-primary, #3b82f6);
344
+ }
345
+
346
+ .inkpen-link-card__image {
347
+ background: rgba(255, 255, 255, 0.05);
348
+ }
349
+ }
350
+
351
+ /* ==========================================================================
352
+ Mobile Optimizations
353
+ ========================================================================== */
354
+
355
+ @media (max-width: 640px) {
356
+ .inkpen-embed__placeholder {
357
+ padding: 2rem 1rem;
358
+ }
359
+
360
+ .inkpen-embed__placeholder-icon {
361
+ width: 48px;
362
+ height: 48px;
363
+ font-size: 1.5rem;
364
+ }
365
+
366
+ .inkpen-link-card {
367
+ flex-direction: column;
368
+ }
369
+
370
+ .inkpen-link-card__image {
371
+ width: 100%;
372
+ height: 140px;
373
+ }
374
+
375
+ /* Center TikTok on mobile */
376
+ .inkpen-embed[data-provider="tiktok"] .inkpen-embed__wrapper {
377
+ max-width: 100%;
378
+ }
379
+ }
380
+
381
+ @media (hover: none) and (pointer: coarse) {
382
+ .inkpen-embed__load-btn {
383
+ padding: 0.75rem 1.5rem;
384
+ font-size: 1rem;
385
+ }
386
+
387
+ .inkpen-embed__remove {
388
+ width: 36px;
389
+ height: 36px;
390
+ }
391
+ }
392
+
393
+ /* ==========================================================================
394
+ Loading Animation
395
+ ========================================================================== */
396
+
397
+ .inkpen-embed__wrapper::before {
398
+ content: "";
399
+ position: absolute;
400
+ inset: 0;
401
+ background: linear-gradient(
402
+ 90deg,
403
+ transparent,
404
+ rgba(255, 255, 255, 0.1),
405
+ transparent
406
+ );
407
+ animation: inkpen-embed-shimmer 1.5s ease-in-out infinite;
408
+ pointer-events: none;
409
+ z-index: 1;
410
+ }
411
+
412
+ .inkpen-embed__wrapper iframe:not([src=""]) + .inkpen-embed__wrapper::before,
413
+ .inkpen-embed__wrapper--widget::before,
414
+ .inkpen-embed__wrapper--script::before {
415
+ display: none;
416
+ }
417
+
418
+ @keyframes inkpen-embed-shimmer {
419
+ 0% {
420
+ transform: translateX(-100%);
421
+ }
422
+ 100% {
423
+ transform: translateX(100%);
424
+ }
425
+ }
426
+
427
+ /* ==========================================================================
428
+ Reduced Motion
429
+ ========================================================================== */
430
+
431
+ @media (prefers-reduced-motion: reduce) {
432
+ .inkpen-embed__load-btn,
433
+ .inkpen-link-card,
434
+ .inkpen-embed__wrapper::before {
435
+ transition: none;
436
+ animation: none;
437
+ }
438
+ }
439
+
440
+ /* ==========================================================================
441
+ Print Styles
442
+ ========================================================================== */
443
+
444
+ @media print {
445
+ .inkpen-embed__placeholder,
446
+ .inkpen-embed__wrapper {
447
+ display: none;
448
+ }
449
+
450
+ .inkpen-embed::after {
451
+ content: "[Embedded content: " attr(data-provider) "]";
452
+ display: block;
453
+ padding: 1rem;
454
+ background: #f3f4f6;
455
+ border: 1px solid #e5e7eb;
456
+ border-radius: 4px;
457
+ font-style: italic;
458
+ color: #6b7280;
459
+ }
460
+
461
+ .inkpen-link-card {
462
+ border: 1px solid #ccc;
463
+ }
464
+
465
+ .inkpen-link-card__image {
466
+ display: none;
467
+ }
468
+ }