milkdown-inline-diff 1.0.2
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 +207 -0
- package/dist/diff-config.d.ts +11 -0
- package/dist/diff-config.d.ts.map +1 -0
- package/dist/diff-tooltip.d.ts +37 -0
- package/dist/diff-tooltip.d.ts.map +1 -0
- package/dist/diffDecorationState.d.ts +7 -0
- package/dist/diffDecorationState.d.ts.map +1 -0
- package/dist/extended-table-schema.d.ts +2 -0
- package/dist/extended-table-schema.d.ts.map +1 -0
- package/dist/index.cjs +75 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26590 -0
- package/dist/markdown-diff.d.ts +52 -0
- package/dist/markdown-diff.d.ts.map +1 -0
- package/dist/myers-diff.d.ts +7 -0
- package/dist/myers-diff.d.ts.map +1 -0
- package/package.json +57 -0
- package/src/diff-config.ts +28 -0
- package/src/diff-tooltip.ts +302 -0
- package/src/diffDecorationState.ts +48 -0
- package/src/extended-table-schema.ts +11 -0
- package/src/index.ts +43 -0
- package/src/markdown-diff.ts +971 -0
- package/src/myers-diff.ts +134 -0
- package/src/style.css +152 -0
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# milkdown-inline-diff
|
|
2
|
+
|
|
3
|
+
Block-level Markdown diff and merge controls for Milkdown editors.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
`milkdown-inline-diff` compares Markdown documents as block structures instead of raw text lines. It is designed for in-editor review flows where users need to inspect and merge changes without leaving the editor.
|
|
10
|
+
|
|
11
|
+
It works well for:
|
|
12
|
+
|
|
13
|
+
- `heading`
|
|
14
|
+
- `paragraph`
|
|
15
|
+
- `blockquote`
|
|
16
|
+
- nested `blockquote`
|
|
17
|
+
- `list`
|
|
18
|
+
- nested `list`
|
|
19
|
+
- `table`
|
|
20
|
+
- `code block`
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pnpm add milkdown-inline-diff
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
You also need the normal Milkdown editor dependencies used by your app.
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { Editor } from "@milkdown/core";
|
|
34
|
+
import { commonmark } from "@milkdown/preset-commonmark";
|
|
35
|
+
import {
|
|
36
|
+
diffConfig,
|
|
37
|
+
diffPlugins,
|
|
38
|
+
} from "milkdown-inline-diff";
|
|
39
|
+
import "milkdown-inline-diff/style.css";
|
|
40
|
+
|
|
41
|
+
const editor = Editor.make()
|
|
42
|
+
.use(commonmark)
|
|
43
|
+
.use(diffPlugins)
|
|
44
|
+
.config(
|
|
45
|
+
diffConfig({
|
|
46
|
+
acceptButtonTitle: "Accept Change",
|
|
47
|
+
rejectButtonTitle: "Keep Original",
|
|
48
|
+
originContent: "# Original",
|
|
49
|
+
modifiedContent: "# Modified",
|
|
50
|
+
}),
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
await editor.create();
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
If both `originContent` and `modifiedContent` are provided, the plugin will automatically enter diff mode after the editor view is ready.
|
|
57
|
+
|
|
58
|
+
## Public API
|
|
59
|
+
|
|
60
|
+
### `diffPlugins`
|
|
61
|
+
|
|
62
|
+
Milkdown plugin array used with:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
editor.use(diffPlugins);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### `diffConfig(options)`
|
|
69
|
+
|
|
70
|
+
Configuration helper used with:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
editor.config(diffConfig({ ... }));
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
interface DiffConfig {
|
|
78
|
+
acceptButtonTitle?: string;
|
|
79
|
+
rejectButtonTitle?: string;
|
|
80
|
+
originContent?: string;
|
|
81
|
+
modifiedContent?: string;
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### `diff(ctx, modifiedContent, originContent?)`
|
|
86
|
+
|
|
87
|
+
Enters diff mode on demand.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
editor.action((ctx) => {
|
|
91
|
+
diff(ctx, modifiedContent, originContent);
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Use this when you want to trigger comparison after editor creation, after loading remote content, or after switching between document versions.
|
|
96
|
+
|
|
97
|
+
### `jumpTo(ctx, index)`
|
|
98
|
+
|
|
99
|
+
Moves focus to a specific diff group.
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
editor.action((ctx) => {
|
|
103
|
+
jumpTo(ctx, 0);
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
This is useful for custom navigation bars, side panels, or review workflows.
|
|
108
|
+
|
|
109
|
+
### `merge(ctx, action, index, all?)`
|
|
110
|
+
|
|
111
|
+
Accepts or rejects a diff group, or resolves all groups at once.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
editor.action((ctx) => {
|
|
115
|
+
merge(ctx, "accept", 0);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
editor.action((ctx) => {
|
|
119
|
+
merge(ctx, "reject", 0, true);
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### `getDiffState(ctx)`
|
|
124
|
+
|
|
125
|
+
Returns the current diff state for external UI.
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
const state = editor.action((ctx) => getDiffState(ctx));
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The returned state includes:
|
|
132
|
+
|
|
133
|
+
- `count`: total number of diff groups
|
|
134
|
+
- `currentIndex`: current focused diff group index, or `-1` before the first group
|
|
135
|
+
|
|
136
|
+
This is the function to use when building your own merge bar, status panel, or conflict navigator.
|
|
137
|
+
|
|
138
|
+
## Typical Review Flow
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
editor.use(diffPlugins).config(
|
|
142
|
+
diffConfig({
|
|
143
|
+
acceptButtonTitle: "Accept Change",
|
|
144
|
+
rejectButtonTitle: "Keep Original",
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
editor.action((ctx) => {
|
|
149
|
+
diff(ctx, modifiedMarkdown, originMarkdown);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const state = editor.action((ctx) => getDiffState(ctx));
|
|
153
|
+
|
|
154
|
+
editor.action((ctx) => {
|
|
155
|
+
jumpTo(ctx, state.currentIndex + 1);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
editor.action((ctx) => {
|
|
159
|
+
merge(ctx, "accept", state.currentIndex);
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Listening For Changes
|
|
164
|
+
|
|
165
|
+
If you want to keep external UI in sync with the editor, listen to Milkdown or Crepe update events and read diff state inside the callback.
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
const syncDiffState = () => {
|
|
169
|
+
const state = editor.action((ctx) => getDiffState(ctx));
|
|
170
|
+
setDiffState(state);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
crepe.on((listener) => {
|
|
174
|
+
listener.mounted(syncDiffState);
|
|
175
|
+
listener.updated(syncDiffState);
|
|
176
|
+
listener.selectionUpdated(syncDiffState);
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
This pattern is used in the React demo to drive the custom merge bar.
|
|
181
|
+
|
|
182
|
+
## Demo
|
|
183
|
+
|
|
184
|
+
The repository includes a runnable React demo in [examples/react](/Users/binzhang/Documents/falcon/milkdown-inline-diff/examples/react).
|
|
185
|
+
|
|
186
|
+
It demonstrates:
|
|
187
|
+
|
|
188
|
+
- `editor.use(diffPlugins).config(diffConfig(...))`
|
|
189
|
+
- automatic diff on initial content
|
|
190
|
+
- custom tooltip button titles
|
|
191
|
+
- custom merge bar UI driven by `getDiffState(ctx)`
|
|
192
|
+
- `jumpTo` navigation
|
|
193
|
+
- `merge(..., all)` bulk actions
|
|
194
|
+
|
|
195
|
+
## Styling
|
|
196
|
+
|
|
197
|
+
Import the plugin stylesheet once:
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
import "milkdown-inline-diff/style.css";
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
You can then override the tooltip and review UI styles in your app theme if needed.
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Ctx } from '@milkdown/ctx';
|
|
2
|
+
export interface DiffConfig {
|
|
3
|
+
acceptButtonTitle?: string;
|
|
4
|
+
rejectButtonTitle?: string;
|
|
5
|
+
originContent?: string;
|
|
6
|
+
modifiedContent?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const defaultDiffConfig: DiffConfig;
|
|
9
|
+
export declare const diffConfigCtx: import('@milkdown/kit/utils').$Ctx<DiffConfig, "diffInlineConfig">;
|
|
10
|
+
export declare function diffConfig(config?: DiffConfig): (ctx: Ctx) => void;
|
|
11
|
+
//# sourceMappingURL=diff-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-config.d.ts","sourceRoot":"","sources":["../src/diff-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAGzC,MAAM,WAAW,UAAU;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,eAAO,MAAM,iBAAiB,EAAE,UAG/B,CAAC;AAEF,eAAO,MAAM,aAAa,oEAGzB,CAAC;AAEF,wBAAgB,UAAU,CAAC,MAAM,GAAE,UAAe,IACxC,KAAK,GAAG,UAMjB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Ctx, MilkdownPlugin } from '@milkdown/ctx';
|
|
2
|
+
import { EditorState, PluginView } from '@milkdown/prose/state';
|
|
3
|
+
import { EditorView, Decoration } from '@milkdown/prose/view';
|
|
4
|
+
export declare const onMergeCtx: import('@milkdown/kit/utils').$Ctx<((action: "accept" | "reject", index: number) => void) | undefined, "onMergeCtx">;
|
|
5
|
+
export declare const diffToolTooltip: import('@milkdown/kit/plugin/tooltip').TooltipPlugin<"MERGE_TOOL", any>;
|
|
6
|
+
export declare class DiffTooltipView implements PluginView {
|
|
7
|
+
private ctx;
|
|
8
|
+
private editView;
|
|
9
|
+
private tooltipProvider;
|
|
10
|
+
private showRect?;
|
|
11
|
+
private shouldShow;
|
|
12
|
+
private currentGroupIndex?;
|
|
13
|
+
private currentPos?;
|
|
14
|
+
private currentDisplayPos?;
|
|
15
|
+
private scrollTarget;
|
|
16
|
+
tooltipElement: HTMLDivElement;
|
|
17
|
+
acceptButton: HTMLButtonElement;
|
|
18
|
+
rejectButton: HTMLButtonElement;
|
|
19
|
+
constructor(ctx: Ctx, editView: EditorView);
|
|
20
|
+
handleScroll: () => void;
|
|
21
|
+
handleAccept(): void;
|
|
22
|
+
handleReject(): void;
|
|
23
|
+
toggleShow(): void;
|
|
24
|
+
show(groupIndex: number, rect: DOMRect, pos?: number): void;
|
|
25
|
+
hide: () => void;
|
|
26
|
+
hideImmediate: () => void;
|
|
27
|
+
isVisible(): boolean;
|
|
28
|
+
update(view: EditorView, _prevState?: EditorState): void;
|
|
29
|
+
destroy: () => void;
|
|
30
|
+
}
|
|
31
|
+
export declare const diffTooltipPlugins: MilkdownPlugin[];
|
|
32
|
+
export declare const tooltipViewConfig: (ctx: Ctx) => void;
|
|
33
|
+
export declare function shouldShowMergeToolForPos(ctx: Ctx, pos: number): {
|
|
34
|
+
index: number;
|
|
35
|
+
decoration: Decoration;
|
|
36
|
+
} | undefined;
|
|
37
|
+
//# sourceMappingURL=diff-tooltip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-tooltip.d.ts","sourceRoot":"","sources":["../src/diff-tooltip.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGzD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAOlD,eAAO,MAAM,UAAU,+CACX,QAAQ,GAAG,QAAQ,SAAS,MAAM,KAAK,IAAI,4BAE7B,CAAC;AAE3B,eAAO,MAAM,eAAe,yEAA+B,CAAC;AAE5D,qBAAa,eAAgB,YAAW,UAAU;IAapC,OAAO,CAAC,GAAG;IAAO,OAAO,CAAC,QAAQ;IAZ9C,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,CAAU;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,iBAAiB,CAAC,CAAS;IACnC,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAAC,CAAS;IACnC,OAAO,CAAC,YAAY,CAA4B;IAEhD,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,iBAAiB,CAAC;IAChC,YAAY,EAAE,iBAAiB,CAAC;gBAEZ,GAAG,EAAE,GAAG,EAAU,QAAQ,EAAE,UAAU;IA+C1D,YAAY,aASV;IAEF,YAAY,IAAI,IAAI;IAMpB,YAAY,IAAI,IAAI;IAMpB,UAAU;IAYV,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM;IAUpD,IAAI,aAGF;IAEF,aAAa,aAIX;IAEF,SAAS,IAAI,OAAO;IAIpB,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,WAAW;IAWjD,OAAO,aAML;CACH;AAYD,eAAO,MAAM,kBAAkB,EAAE,cAAc,EAG9C,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,KAAK,GAAG,SA8BzC,CAAC;AAoDF,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,MAAM,GACV;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,GAAG,SAAS,CAiBvD"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DecorationSet } from '@milkdown/prose/view';
|
|
2
|
+
export interface DiffDecorationState {
|
|
3
|
+
decorations: DecorationSet | null;
|
|
4
|
+
}
|
|
5
|
+
export declare const diffDecorationState: import('@milkdown/kit/utils').$Ctx<DiffDecorationState, "diffDecorationState">;
|
|
6
|
+
export declare const diffDecorationPlugin: import('@milkdown/kit/utils').$Prose;
|
|
7
|
+
//# sourceMappingURL=diffDecorationState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diffDecorationState.d.ts","sourceRoot":"","sources":["../src/diffDecorationState.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,aAAa,GAAG,IAAI,CAAC;CACnC;AAED,eAAO,MAAM,mBAAmB,gFAQ/B,CAAC;AAEF,eAAO,MAAM,oBAAoB,sCA6B/B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extended-table-schema.d.ts","sourceRoot":"","sources":["../src/extended-table-schema.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB,oDAQ9B,CAAC"}
|