inkpen 0.8.2 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ca02bbf14f1a82f2624cb85480bba7a2dd63cfe703d7444c88799c2408968e0
4
- data.tar.gz: 71112fa7c30ef904c324e4fd24626af17614e6b783fece8fa4f06b19fea5911b
3
+ metadata.gz: 53bb272d92be9ebaaa8096f29650efdaf398d94869ba2816a6ce1865934ef052
4
+ data.tar.gz: 5d1e03b894fcd2a74f58b04e9d647483bd8536111aecb6d43f13e1b6defbe2bd
5
5
  SHA512:
6
- metadata.gz: 268d8fc4f8383fa058b9b85b5732b6723b87a4de563bd633f26286807bccdad90b1f03916b23a581ec2928b11005af693908848c9e55007ff65ef166f337bd19
7
- data.tar.gz: 66cea9159d7788cd16b4157fd711507729ab965169f3f19e4a8d5adf1ce3f50d9db72d99b22c0d7f66e6f4b19ded15e2f0da523df49e530b6f1fbb3f8368b162
6
+ metadata.gz: b54aed81a7ed029d17713ec708326ebe26e55eb1d042cdd6d8d5da68adc972767525efd0e828fff0d4d3930ce82939e5cf901dec6c30c24cd1ec40a483c46d0e
7
+ data.tar.gz: d11b40ec2bed5b98667ffca8e8689ea8e97a03ef8d5da060ac530cfd29fb74064297baacca19993f9a94a60413a743d83114bd3fd93c75d25f352e2efc051566
data/README.md CHANGED
@@ -27,6 +27,26 @@ Then run:
27
27
  bundle install
28
28
  ```
29
29
 
30
+ ### Stylesheets (important — must be included by the host)
31
+
32
+ The gem ships a separate stylesheet at `inkpen/editor.css`. **It is not auto-loaded** by your host app's layout. You must include it yourself, typically in `app/views/layouts/application.html.erb`:
33
+
34
+ ```erb
35
+ <%= stylesheet_link_tag "inkpen/editor", "data-turbo-track": "reload" %>
36
+ ```
37
+
38
+ If you have other layouts (fullscreen tool layouts, custom marketing layouts, etc.) and Inkpen mounts on any view they render, **each layout must include the stylesheet**. Forgetting this is the most common "the editor renders but looks broken" failure mode — TipTap mounts fine in JS, but no Inkpen styles apply.
39
+
40
+ If you also use any of the visual extensions below, include their stylesheets too (Sprockets `*= require inkpen/<name>` or Propshaft `<%= stylesheet_link_tag "inkpen/<name>" %>`):
41
+
42
+ - `inkpen/advanced_table`, `inkpen/inkpen_table` — table styles
43
+ - `inkpen/callout`, `inkpen/columns`, `inkpen/database`, `inkpen/document_section` — block extensions
44
+ - `inkpen/drag_drop`, `inkpen/block_gutter`, `inkpen/sticky_toolbar` — chrome
45
+ - `inkpen/embed`, `inkpen/enhanced_image`, `inkpen/file_attachment`, `inkpen/footnotes`, `inkpen/toc` — content blocks
46
+ - `inkpen/mention`, `inkpen/slash_menu`, `inkpen/preformatted`, `inkpen/search_replace`, `inkpen/section`, `inkpen/toggle`, `inkpen/markdown_mode`, `inkpen/export`, `inkpen/animations` — UX
47
+
48
+ Only `inkpen/editor` is added to the asset precompile list automatically; everything else opts in.
49
+
30
50
  ## Configuration
31
51
 
32
52
  Configure Inkpen globally in an initializer:
@@ -303,6 +323,34 @@ The editor is controlled by `inkpen--editor` Stimulus controller. Connect it to
303
323
  </div>
304
324
  ```
305
325
 
326
+ The `extensions-value` array gates which TipTap extensions the editor instantiates. The full bundle ships every extension, but unconfigured ones don't run — they just sit in the bundle. (A future spec — `02-lazy-load-and-extension-gating` in the planning surface — will gate the bundle download too, so a lite editor downloads only what it asks for. As of `0.8.x` the gate is runtime-only, not bundle-time.)
327
+
328
+ Supported extension names: `bold`, `italic`, `link`, `heading`, `bullet_list`, `ordered_list`, `task_list`, `code_block`, `code`, `strike`, `underline`, `subscript`, `superscript`, `highlight`, `typography`, `placeholder`, `blockquote`, `horizontal_rule`, `hard_break`, `history`, `dropcursor`, `gapcursor`, `image`, `youtube`, `character_count`, `bubble_menu`, `floating_menu`, `mention`, `table`, `inkpen_table`, `task_item`, `callout`, `columns`, `database`, `document_section`, `embed`, `enhanced_image`, `file_attachment`, `slash_commands`, `block_commands`, `block_gutter`, `drag_handle`, `toggle_block`, `preformatted`, `section`, `section_title`, `table_of_contents`, `export_commands`, `content_embed`.
329
+
330
+ ### Public events
331
+
332
+ The editor controller dispatches `CustomEvent`s that bubble up the DOM, so any ancestor element (including the host's `application.js`) can listen with `element.addEventListener("inkpen:<name>", handler)`. All events include `detail.controller` pointing at the dispatching `EditorController` instance.
333
+
334
+ | Event | When it fires | Payload (`detail`) |
335
+ | --- | --- | --- |
336
+ | `inkpen:ready` | Editor is mounted and ready to use | `{ editor }` |
337
+ | `inkpen:change` | Content changed | `{ content, title, subtitle, body, wordCount, characterCount }` |
338
+ | `inkpen:focus` | Editor gained focus | `{}` |
339
+ | `inkpen:blur` | Editor lost focus | `{}` |
340
+ | `inkpen:selection-change` | Selection or marks changed | `{ selection, marks }` |
341
+ | `inkpen:autosave` | Autosave fired | `{ content, timestamp }` |
342
+ | `inkpen:mode-change` | WYSIWYG/split/markdown view toggled | `{ mode, previousMode }` |
343
+ | `inkpen:error` | Recoverable error | `{ kind, error?, message? }` |
344
+ | `inkpen:slash-command` | User picked an item from the `/` slash menu | `{ commandId, range, editor }` |
345
+ | `inkpen:export-success` | Export action succeeded | `{ message }` |
346
+ | `inkpen:export-error` | Export action failed | `{ message }` |
347
+ | `inkpen:widget-inserted` | Sticky-toolbar widget inserted | `{ type, data }` |
348
+ | `inkpen:insert-widget`, `inkpen:request-file`, `inkpen:request-image`, `inkpen:request-embed` | Sticky-toolbar requests host to handle an action | varies; see `sticky_toolbar_controller.js` |
349
+
350
+ `inkpen:error` is the most useful one to wire to a host-side error tracker — log it globally so any future failure mode is visible. Today's `kind` values include `module-load` (a TipTap module failed to import) and `markdown-import` (reserved for the future markdown-import path).
351
+
352
+ `inkpen:slash-command` is how host code adds custom slash-menu actions. The `commandId` is whatever you registered in the slash-commands extension config; intercept the event, prevent default if your code handles it, otherwise let the editor's default action run.
353
+
306
354
  ## Architecture
307
355
 
308
356
  ```
@@ -1,87 +1,50 @@
1
- // Inkpen - TipTap-based rich text editor for Rails
2
- // Entry point for importmap
1
+ // Inkpen TipTap-based rich text editor for Rails.
2
+ //
3
+ // This is the entry the host's importmap pins as `inkpen`. The host
4
+ // does `import "inkpen"` from its application.js; the side effect of
5
+ // that import is registering the three Stimulus controllers below.
6
+ // Everything else (TipTap core, every extension, ProseMirror, etc.)
7
+ // is loaded LAZILY by the EditorController via gated dynamic imports,
8
+ // not statically here.
9
+ //
10
+ // Spec 02 (2026-05-17, gem 0.9.0): the previous index.js statically
11
+ // imported 17 custom extensions and re-exported them as named exports.
12
+ // That made every consumer pay the full extension graph at module-eval
13
+ // time, even when their editor enabled only a subset. Those static
14
+ // imports are gone. Extension classes are now loaded on demand by
15
+ // editor_controller.js#loadEditorModules based on the editor instance's
16
+ // `extensions-value`. Hosts that previously did `import { Section }
17
+ // from "inkpen"` must now either:
18
+ //
19
+ // a) Configure the editor's extensions-value to include "section"
20
+ // (preferred — the controller manages the extension lifecycle)
21
+ // b) Import the extension's path directly through a custom importmap
22
+ // pin (advanced; only if you need direct programmatic access)
23
+ //
24
+ // InventList today only does `import "inkpen"` and configures
25
+ // extensions-value on the data-controller element — the supported and
26
+ // recommended pattern.
3
27
 
4
28
  import { Application } from "@hotwired/stimulus"
5
29
  import EditorController from "inkpen/controllers/editor_controller"
6
30
  import ToolbarController from "inkpen/controllers/toolbar_controller"
7
31
  import StickyToolbarController from "inkpen/controllers/sticky_toolbar_controller"
8
32
 
9
- // ============================================
10
- // IMPORTANT: Register controllers IMMEDIATELY before any async code
11
- // This ensures controllers are available when Stimulus scans the DOM
12
- // ============================================
33
+ // Register controllers IMMEDIATELY at module-eval. Stimulus scans the
34
+ // DOM as soon as it boots; controllers not registered by then won't
35
+ // connect to their elements.
13
36
  const application = window.Stimulus || Application.start()
14
37
 
15
38
  application.register("inkpen--editor", EditorController)
16
39
  application.register("inkpen--toolbar", ToolbarController)
17
40
  application.register("inkpen--sticky-toolbar", StickyToolbarController)
18
41
 
19
- // TipTap extensions (static imports)
20
- import { Section } from "inkpen/extensions/section"
21
- import { Preformatted } from "inkpen/extensions/preformatted"
22
- import { SlashCommands } from "inkpen/extensions/slash_commands"
23
- import { BlockGutter } from "inkpen/extensions/block_gutter"
24
- import { DragHandle } from "inkpen/extensions/drag_handle"
25
- import { ToggleBlock, ToggleSummary } from "inkpen/extensions/toggle_block"
26
- import { Columns, Column } from "inkpen/extensions/columns"
27
- import { Callout } from "inkpen/extensions/callout"
28
- import { BlockCommands } from "inkpen/extensions/block_commands"
29
- import { EnhancedImage } from "inkpen/extensions/enhanced_image"
30
- import { FileAttachment } from "inkpen/extensions/file_attachment"
31
- import { Embed } from "inkpen/extensions/embed"
32
- import { AdvancedTable, AdvancedTableRow, AdvancedTableCell, AdvancedTableHeader } from "inkpen/extensions/advanced_table"
33
- import { TableOfContents } from "inkpen/extensions/table_of_contents"
34
- import { Database } from "inkpen/extensions/database"
35
- import { DocumentSection } from "inkpen/extensions/document_section"
36
- import { SectionTitle } from "inkpen/extensions/section_title"
37
-
38
- // InkpenTable is loaded lazily to prevent import failures from breaking the library
39
- let InkpenTable, InkpenTableRow, InkpenTableCell, InkpenTableHeader
40
- try {
41
- const mod = await import("inkpen/extensions/inkpen_table")
42
- InkpenTable = mod.InkpenTable
43
- InkpenTableRow = mod.InkpenTableRow
44
- InkpenTableCell = mod.InkpenTableCell
45
- InkpenTableHeader = mod.InkpenTableHeader
46
- } catch (e) {
47
- console.warn("Inkpen: InkpenTable extension not available:", e.message)
48
- }
49
-
50
- // Export controllers
42
+ // Re-export the controller classes for hosts that want to wire them
43
+ // to their own Stimulus application instance (rare; most consumers
44
+ // just use the side-effect registration above).
51
45
  export { EditorController, ToolbarController, StickyToolbarController }
52
46
 
53
- // Export extensions for custom use
54
- export {
55
- Section,
56
- DocumentSection,
57
- SectionTitle,
58
- Preformatted,
59
- SlashCommands,
60
- BlockGutter,
61
- DragHandle,
62
- ToggleBlock,
63
- ToggleSummary,
64
- Columns,
65
- Column,
66
- Callout,
67
- BlockCommands,
68
- EnhancedImage,
69
- FileAttachment,
70
- Embed,
71
- // InkpenTable - Notion-style enhanced tables (recommended)
72
- InkpenTable,
73
- InkpenTableRow,
74
- InkpenTableCell,
75
- InkpenTableHeader,
76
- // AdvancedTable - Legacy (use InkpenTable instead)
77
- AdvancedTable,
78
- AdvancedTableRow,
79
- AdvancedTableCell,
80
- AdvancedTableHeader,
81
- TableOfContents,
82
- Database
83
- }
84
-
85
- // Export functionality is available separately:
86
- // import { ExportCommands } from "inkpen/extensions/export_commands"
87
- // import { exportToMarkdown, ... } from "inkpen/export"
47
+ // Extension classes are no longer exported from this entry. Configure
48
+ // them via the `data-inkpen--editor-extensions-value` attribute on the
49
+ // editor element; editor_controller.js loads each one lazily. See the
50
+ // README "Stimulus Controller" + "Public events" sections.