@oix1987/yjd 2.1.2 → 2.2.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.
package/README.md CHANGED
@@ -30,11 +30,12 @@ Every preset is built from the same `/core` entry — pick a profile, tree-shake
30
30
  | Comment box | bold · italic · link · list · image · mention + `fromTextarea` | **~26 KB** |
31
31
  | Basic | + strike · headings · lists · align | **~25 KB** |
32
32
  | Standard | + colour · image · table · find · code view | **~38 KB** |
33
- | Full (all-in-one) | everything, CSS inlined | **~64 KB** |
33
+ | + AI assistant | any preset + `ai` module (BYO model, no SDK bundled) | **+~2 KB** |
34
+ | Full (all-in-one) | everything, CSS inlined | **~66 KB** |
34
35
 
35
36
  > All figures are measured gzip. Tree-shake from the `/core` entry to land near the
36
37
  > top of the table; the all-in-one default (`import yjd from '@oix1987/yjd'`) is the
37
- > ~64 KB row because it registers every format/module and inlines the CSS. For
38
+ > ~66 KB row because it registers every format/module and inlines the CSS. For
38
39
  > comparison, Quill 2 is ~60 KB. The standalone stylesheet is ~10 KB gzip — link it
39
40
  > once (and skip `StylesLoader`) to keep it out of the JS.
40
41
 
@@ -139,7 +140,7 @@ const ed = Editor.fromTextarea('#comment', {
139
140
 
140
141
  **Formats** — `bold` · `italic` · `underline` · `strike` · `subscript` · `superscript` · `color` · `background` · `link` · `heading` · `font-family` · `text-size` · `line-height` · `capitalization` · `text-align` · `list` · `indent-increase` · `indent-decrease` · `image` · `video` · `table` · `emoji` · `tag`
141
142
 
142
- **Modules** — `toolbar` · `history` · `slash-menu` · `mention` · `block-toolbar` (bubble bar) · `table-toolbar` · `find-replace` · `code-view` · `resize-handles`
143
+ **Modules** — `toolbar` · `history` · `slash-menu` · `mention` · `ai` (BYO-model assistant) · `block-toolbar` (bubble bar) · `table-toolbar` · `find-replace` · `code-view` · `resize-handles`
143
144
 
144
145
  ## Methods
145
146
 
@@ -229,6 +230,63 @@ Inserts a token that serializes with its id:
229
230
  If a `source` item has no `avatar_url`, pass `icon` (inline SVG) for special entries
230
231
  like “@all”. Menus are portaled to `<body>` but inherit the editor's `--rte-*` theme.
231
232
 
233
+ ### AI assistant (bring your own model)
234
+
235
+ Turn yjd into a "write-with-AI" surface **without bundling any model**. Like
236
+ `mention.source`, you supply a `complete` hook that calls whatever LLM you like
237
+ (Claude, your own endpoint, anything). The module is **inert until you do**, and
238
+ **tree-shakes to 0** when unused — so the AI code never reaches users who don't
239
+ opt in.
240
+
241
+ ```js
242
+ new yjd('#editor', {
243
+ ai: {
244
+ // REQUIRED. Resolve to the generated text. Stream by calling onToken with
245
+ // each chunk; if you only stream, return undefined and chunks are joined.
246
+ complete: async ({ action, prompt, text, signal }, onToken) => {
247
+ const res = await fetch('/api/ai', {
248
+ method: 'POST', signal,
249
+ body: JSON.stringify({ action, prompt, text }),
250
+ });
251
+ return (await res.json()).text;
252
+ },
253
+ autocomplete: true, // optional: inline ghost-text, Tab to accept
254
+ },
255
+ });
256
+ ```
257
+
258
+ **What the user gets:**
259
+
260
+ - **Selection toolbar** — select text and a floating bar offers *Improve · Fix
261
+ spelling & grammar · Shorten · Lengthen · Simplify · Summarize* plus a free-form
262
+ **Ask AI…** box. The result is previewed with **Accept / Retry / Discard** — the
263
+ user always stays in control (nothing overwrites their text until they accept).
264
+ - **Ghost-text autocomplete** (opt-in) — a greyed inline suggestion as they type;
265
+ **Tab** accepts, any other key dismisses. Debounced and request-cancelling, so it
266
+ never blocks typing.
267
+
268
+ Customise the actions, or drive it programmatically:
269
+
270
+ ```js
271
+ ai: { complete, actions: [{ id: 'tr', label: 'Translate → FR', prompt: 'Translate to French.' }] }
272
+
273
+ editor.ai.run('Make this sound friendlier'); // run on the current selection
274
+ editor.on('ai:accept', ({ result }) => {}); // ai:start · ai:done · ai:error · ai:accept · ai:discard
275
+ ```
276
+
277
+ Building your own agent UI? The same primitives are public:
278
+
279
+ ```js
280
+ editor.getSelection(); // { text, html, isEmpty, range }
281
+ editor.replaceSelection(text, { asText: true }); // sanitized, undo-aware
282
+ const s = editor.streamInto(); // token-by-token sink
283
+ s.append('Hel'); s.append('lo'); s.commit(); // or s.cancel() to undo the stream
284
+ ```
285
+
286
+ Nothing the module renders ever lives in the editable DOM, so `getContent()` /
287
+ `getJSON()` / `onChange` stay clean. Menus portal to `<body>` but inherit the
288
+ editor's `--rte-*` theme.
289
+
232
290
  ### Toolbar presets
233
291
 
234
292
  ```js
@@ -265,7 +323,8 @@ renderStatic(post.body_html, document.querySelector('#post'));
265
323
 
266
324
  - **Events** (via `editor.on(name, cb)` / `editor.off(name, cb)`): `change`,
267
325
  `image:upload` · `image:uploaded` · `image:error`, `file:upload` · `file:uploaded`
268
- · `file:error`, `mention:select`, `content:overflow` (when `maxContentSize` exceeded).
326
+ · `file:error`, `mention:select`, `ai:start` · `ai:done` · `ai:accept` · `ai:discard`
327
+ · `ai:error`, `content:overflow` (when `maxContentSize` exceeded).
269
328
  - `editor.editor` is the public contentEditable element (attach your own listeners).
270
329
  - **Markdown dialect** — GFM-ish: headings `#`–`######`, `**bold**`, `*italic*`,
271
330
  `~~strike~~`, `` `code` ``, fenced ``` ``` ```, `>` quotes, `-`/`1.` lists,
package/core.js CHANGED
@@ -62,6 +62,7 @@ export { default as CodeView } from './lib/modules/code-view.js';
62
62
  export { default as FindReplace } from './lib/modules/find-replace.js';
63
63
  export { default as SlashMenu } from './lib/modules/slash-menu.js';
64
64
  export { default as Mention } from './lib/modules/mention.js';
65
+ export { default as Ai } from './lib/modules/ai.js';
65
66
  export { default as ResizeHandles } from './lib/modules/resize-handles.js';
66
67
 
67
68
  // UI