inline-attacher 0.0.8 → 0.1.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.
- package/README.md +25 -1
- package/dist/core.d.ts +7 -4
- package/dist/inline-attacher.js +125 -95
- package/dist/inline-attacher.umd.cjs +1 -1
- package/dist/types.d.ts +7 -0
- package/package.json +25 -21
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ npm i inline-attacher
|
|
|
28
28
|
- CodeMirror v6
|
|
29
29
|
|
|
30
30
|
```ts
|
|
31
|
-
import { EditorView } from "codemirror";
|
|
31
|
+
import { EditorView } from "@codemirror/view";
|
|
32
32
|
import { inlineAttachmentExtension } from "inline-attacher";
|
|
33
33
|
|
|
34
34
|
const editor = new EditorView({
|
|
@@ -38,3 +38,27 @@ npm i inline-attacher
|
|
|
38
38
|
parent: document.body,
|
|
39
39
|
});
|
|
40
40
|
```
|
|
41
|
+
|
|
42
|
+
- Custom upload handler
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { attach } from "inline-attacher";
|
|
46
|
+
|
|
47
|
+
const textarea = document.querySelector("textarea");
|
|
48
|
+
|
|
49
|
+
attach(textarea, {
|
|
50
|
+
async uploadHandler({ file, filename, formData }) {
|
|
51
|
+
const response = await myUploader.upload({
|
|
52
|
+
file,
|
|
53
|
+
filename,
|
|
54
|
+
formData,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return { url: response.publicUrl };
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The returned object is handled the same way as the built-in upload response:
|
|
63
|
+
`responseUrlKey` is used to read the uploaded file URL before replacing the
|
|
64
|
+
placeholder text.
|
package/dist/core.d.ts
CHANGED
|
@@ -4,9 +4,10 @@ export declare class InlineAttachment<TInstance> {
|
|
|
4
4
|
editor: Editor<TInstance>;
|
|
5
5
|
filename: string;
|
|
6
6
|
lastValue: string;
|
|
7
|
+
private pendingPlaceholders;
|
|
7
8
|
constructor(editor: Editor<TInstance>, options: Partial<InlineAttachmentOptions>);
|
|
8
9
|
/** Uploads file */
|
|
9
|
-
uploadFile(file: File): Promise<void>;
|
|
10
|
+
uploadFile(file: File, placeholder?: string): Promise<void>;
|
|
10
11
|
/**
|
|
11
12
|
* Returns if the given file is allowed to handle
|
|
12
13
|
*/
|
|
@@ -14,16 +15,18 @@ export declare class InlineAttachment<TInstance> {
|
|
|
14
15
|
/**
|
|
15
16
|
* Handles upload response
|
|
16
17
|
*/
|
|
17
|
-
onFileUploadSucceed(response: Record<string, unknown
|
|
18
|
+
onFileUploadSucceed(response: Record<string, unknown>, placeholder?: string, filename?: string): void;
|
|
18
19
|
/**
|
|
19
20
|
* Called when a file has failed to upload
|
|
20
21
|
*/
|
|
21
|
-
onFileUploadError(error: Error): void;
|
|
22
|
+
onFileUploadError(error: Error, placeholder?: string): void;
|
|
22
23
|
/**
|
|
23
24
|
* Called when a file has been inserted, either by drop or paste
|
|
24
25
|
*/
|
|
25
|
-
onFileInserted(file: File):
|
|
26
|
+
onFileInserted(file: File): string | false;
|
|
26
27
|
handleFiles(files: FileList): void;
|
|
28
|
+
private insertFile;
|
|
29
|
+
private replacePlaceholder;
|
|
27
30
|
/**
|
|
28
31
|
* Called when a paste event occurred
|
|
29
32
|
*/
|
package/dist/inline-attacher.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
var x = (n, t, e) => t in n ? w(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e;
|
|
3
|
-
var o = (n, t, e) => (x(n, typeof t != "symbol" ? t + "" : t, e), e);
|
|
4
|
-
import { EditorView as V } from "@codemirror/view";
|
|
1
|
+
import { EditorView as w } from "@codemirror/view";
|
|
5
2
|
const E = {
|
|
6
3
|
/**
|
|
7
4
|
* URL where the file will be send
|
|
@@ -90,7 +87,7 @@ const E = {
|
|
|
90
87
|
onFileUploaded() {
|
|
91
88
|
}
|
|
92
89
|
};
|
|
93
|
-
async function
|
|
90
|
+
async function P({
|
|
94
91
|
url: n,
|
|
95
92
|
...t
|
|
96
93
|
}) {
|
|
@@ -109,10 +106,10 @@ async function D({
|
|
|
109
106
|
};
|
|
110
107
|
}
|
|
111
108
|
}
|
|
112
|
-
function
|
|
109
|
+
function U(n) {
|
|
113
110
|
return typeof n == "function";
|
|
114
111
|
}
|
|
115
|
-
function
|
|
112
|
+
function y(n, t = "", e = "") {
|
|
116
113
|
const s = t.split(".");
|
|
117
114
|
let i = n;
|
|
118
115
|
for (const r of s)
|
|
@@ -122,47 +119,69 @@ function A(n, t = "", e = "") {
|
|
|
122
119
|
return e;
|
|
123
120
|
return i !== void 0 ? i : e;
|
|
124
121
|
}
|
|
125
|
-
|
|
122
|
+
function T(n, t, e, s = 0) {
|
|
123
|
+
let i = 0;
|
|
124
|
+
for (let r = 0; r <= s; r += 1) {
|
|
125
|
+
const o = n.indexOf(t, i);
|
|
126
|
+
if (o === -1) return n;
|
|
127
|
+
if (r === s)
|
|
128
|
+
return n.slice(0, o) + e + n.slice(o + t.length);
|
|
129
|
+
i = o + t.length;
|
|
130
|
+
}
|
|
131
|
+
return n;
|
|
132
|
+
}
|
|
133
|
+
class F {
|
|
134
|
+
options = E;
|
|
135
|
+
editor;
|
|
136
|
+
filename = "";
|
|
137
|
+
lastValue = "";
|
|
138
|
+
pendingPlaceholders = [];
|
|
126
139
|
constructor(t, e) {
|
|
127
|
-
o(this, "options", E);
|
|
128
|
-
o(this, "editor");
|
|
129
|
-
o(this, "filename", "");
|
|
130
|
-
o(this, "lastValue", "");
|
|
131
140
|
this.editor = t, this.options = { ...E, ...e };
|
|
132
141
|
}
|
|
133
|
-
|
|
134
|
-
async uploadFile(t) {
|
|
142
|
+
async uploadFile(t, e) {
|
|
135
143
|
const {
|
|
136
|
-
defaultExtension:
|
|
137
|
-
remoteFilename:
|
|
138
|
-
uploadFieldName:
|
|
139
|
-
extraParams:
|
|
140
|
-
extraHeaders:
|
|
144
|
+
defaultExtension: s,
|
|
145
|
+
remoteFilename: i,
|
|
146
|
+
uploadFieldName: r,
|
|
147
|
+
extraParams: o,
|
|
148
|
+
extraHeaders: a,
|
|
141
149
|
uploadUrl: c,
|
|
142
|
-
uploadMethod:
|
|
143
|
-
beforeFileUpload:
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (t.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
uploadMethod: d,
|
|
151
|
+
beforeFileUpload: u,
|
|
152
|
+
uploadHandler: f
|
|
153
|
+
} = this.options, p = new FormData(), x = s.replace(/^\./, ""), h = i?.(t) || t.name || `image-${Date.now()}.${x}`;
|
|
154
|
+
if (this.filename = h, p.append(r, t, h), Object.keys(o).forEach((l) => {
|
|
155
|
+
p.append(l, o[l]);
|
|
156
|
+
}), !u?.(p)) return;
|
|
157
|
+
if (f) {
|
|
158
|
+
try {
|
|
159
|
+
const l = await f({
|
|
160
|
+
file: t,
|
|
161
|
+
filename: h,
|
|
162
|
+
formData: p,
|
|
163
|
+
options: this.options
|
|
164
|
+
});
|
|
165
|
+
this.onFileUploadSucceed(l, e, h);
|
|
166
|
+
} catch (l) {
|
|
167
|
+
this.onFileUploadError(
|
|
168
|
+
l instanceof Error ? l : new Error(String(l)),
|
|
169
|
+
e
|
|
170
|
+
);
|
|
171
|
+
}
|
|
154
172
|
return;
|
|
155
|
-
|
|
173
|
+
}
|
|
174
|
+
const { ok: v, value: m } = await P({
|
|
156
175
|
url: c,
|
|
157
|
-
method:
|
|
158
|
-
body:
|
|
159
|
-
headers:
|
|
176
|
+
method: d,
|
|
177
|
+
body: p,
|
|
178
|
+
headers: a
|
|
160
179
|
});
|
|
161
|
-
if (!
|
|
162
|
-
this.onFileUploadError(m);
|
|
180
|
+
if (!v) {
|
|
181
|
+
this.onFileUploadError(m, e);
|
|
163
182
|
return;
|
|
164
183
|
}
|
|
165
|
-
this.onFileUploadSucceed(m);
|
|
184
|
+
this.onFileUploadSucceed(m, e, h);
|
|
166
185
|
}
|
|
167
186
|
/**
|
|
168
187
|
* Returns if the given file is allowed to handle
|
|
@@ -171,73 +190,84 @@ class v {
|
|
|
171
190
|
const { allowedTypes: e } = this.options;
|
|
172
191
|
return e.includes("*") || e.includes(t.type);
|
|
173
192
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const {
|
|
180
|
-
|
|
181
|
-
return;
|
|
182
|
-
const r = A(t, i) || "unknown URL";
|
|
183
|
-
if (!r)
|
|
184
|
-
return;
|
|
185
|
-
const l = /!\[({[^}]+})]\(([^)]+)\)/, c = T(s) ? s(r, t) : s.replace(s.match(l)[1], this.filename).replace(s.match(l)[2], r), p = this.editor.getValue().replace(this.lastValue, c);
|
|
186
|
-
this.editor.setValue(p), (a = (d = this.options).onFileUploaded) == null || a.call(d, r);
|
|
193
|
+
onFileUploadSucceed(t, e, s = this.filename) {
|
|
194
|
+
const { onFileUploadSucceed: i, urlText: r, responseUrlKey: o } = this.options;
|
|
195
|
+
if (!i?.(t)) return;
|
|
196
|
+
const a = typeof e == "string" ? e : e?.text || this.lastValue;
|
|
197
|
+
if (!a) return;
|
|
198
|
+
const c = y(t, o) || "unknown URL", d = /!\[({[^}]+})]\(([^)]+)\)/, u = U(r) ? r(c, t) : r.replace(r.match(d)[1], s).replace(r.match(d)[2], c), f = this.replacePlaceholder(e, a, u);
|
|
199
|
+
this.editor.setValue(f), this.options.onFileUploaded?.(c);
|
|
187
200
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return;
|
|
195
|
-
const e = this.editor.getValue().replace(this.lastValue, this.options.errorText);
|
|
196
|
-
this.editor.setValue(e);
|
|
201
|
+
onFileUploadError(t, e) {
|
|
202
|
+
if (!this.options.onFileUploadError?.(t)) return;
|
|
203
|
+
const s = typeof e == "string" ? e : e?.text || this.lastValue;
|
|
204
|
+
if (!s) return;
|
|
205
|
+
const i = this.replacePlaceholder(e, s, this.options.errorText);
|
|
206
|
+
this.editor.setValue(i);
|
|
197
207
|
}
|
|
198
208
|
/**
|
|
199
209
|
* Called when a file has been inserted, either by drop or paste
|
|
200
210
|
*/
|
|
201
211
|
onFileInserted(t) {
|
|
202
|
-
|
|
203
|
-
|
|
212
|
+
const e = this.insertFile(t);
|
|
213
|
+
return e ? e.text : !1;
|
|
204
214
|
}
|
|
205
215
|
handleFiles(t) {
|
|
206
216
|
Array.from(t).forEach((e) => {
|
|
207
|
-
|
|
217
|
+
if (!this.isFileAllowed(e)) return;
|
|
218
|
+
const s = this.pendingPlaceholders.length, i = this.onFileInserted(e);
|
|
219
|
+
if (!i) return;
|
|
220
|
+
const r = this.pendingPlaceholders[s];
|
|
221
|
+
this.uploadFile(
|
|
222
|
+
e,
|
|
223
|
+
r?.text === i ? r : i
|
|
224
|
+
);
|
|
208
225
|
});
|
|
209
226
|
}
|
|
227
|
+
insertFile(t) {
|
|
228
|
+
if (!this.options.onFileReceived?.(t)) return !1;
|
|
229
|
+
const e = {
|
|
230
|
+
id: /* @__PURE__ */ Symbol("inline-attacher-placeholder"),
|
|
231
|
+
text: this.options.progressText
|
|
232
|
+
};
|
|
233
|
+
return this.pendingPlaceholders.push(e), this.lastValue = e.text, this.editor.insertValue(e.text), e;
|
|
234
|
+
}
|
|
235
|
+
replacePlaceholder(t, e, s) {
|
|
236
|
+
const i = this.editor.getValue();
|
|
237
|
+
if (!t || typeof t == "string")
|
|
238
|
+
return i.replace(e, s);
|
|
239
|
+
const r = this.pendingPlaceholders.findIndex(({ id: o }) => o === t.id);
|
|
240
|
+
return r === -1 ? i.replace(e, s) : (this.pendingPlaceholders.splice(r, 1), T(i, e, s, r));
|
|
241
|
+
}
|
|
210
242
|
/**
|
|
211
243
|
* Called when a paste event occurred
|
|
212
244
|
*/
|
|
213
245
|
onPaste(t) {
|
|
214
|
-
|
|
215
|
-
(e = t.clipboardData) != null && e.files.length && this.handleFiles(t.clipboardData.files);
|
|
246
|
+
t.clipboardData?.files.length && this.handleFiles(t.clipboardData.files);
|
|
216
247
|
}
|
|
217
248
|
/**
|
|
218
249
|
* Called when a drop event occurred
|
|
219
250
|
*/
|
|
220
251
|
onDrop(t) {
|
|
221
|
-
|
|
222
|
-
(e = t.dataTransfer) != null && e.files.length && this.handleFiles(t.dataTransfer.files);
|
|
252
|
+
t.dataTransfer?.files.length && this.handleFiles(t.dataTransfer.files);
|
|
223
253
|
}
|
|
224
254
|
}
|
|
225
|
-
function
|
|
226
|
-
const e = n.scrollTop, s = n.selectionStart
|
|
227
|
-
n.value =
|
|
228
|
-
const
|
|
229
|
-
n.selectionStart =
|
|
255
|
+
function b(n, t) {
|
|
256
|
+
const e = n.scrollTop, s = n.selectionStart ?? 0, i = n.selectionEnd ?? s, r = Math.min(s, i), o = Math.max(s, i), { value: a } = n, c = a.slice(0, r), d = a.slice(o, a.length);
|
|
257
|
+
n.value = c + t + d;
|
|
258
|
+
const u = r + t.length;
|
|
259
|
+
n.selectionStart = u, n.selectionEnd = u, n.scrollTop = e, n.focus();
|
|
230
260
|
}
|
|
231
|
-
class
|
|
261
|
+
class D {
|
|
262
|
+
instance;
|
|
232
263
|
constructor(t) {
|
|
233
|
-
o(this, "instance");
|
|
234
264
|
this.instance = t;
|
|
235
265
|
}
|
|
236
266
|
getValue() {
|
|
237
267
|
return this.instance.value;
|
|
238
268
|
}
|
|
239
269
|
insertValue(t) {
|
|
240
|
-
|
|
270
|
+
b(this.instance, t), this.dispatchInputEvent();
|
|
241
271
|
}
|
|
242
272
|
setValue(t) {
|
|
243
273
|
this.instance.value = t, this.dispatchInputEvent();
|
|
@@ -249,9 +279,9 @@ class b {
|
|
|
249
279
|
}));
|
|
250
280
|
}
|
|
251
281
|
}
|
|
252
|
-
class
|
|
282
|
+
class I extends F {
|
|
253
283
|
constructor(t, e = {}) {
|
|
254
|
-
super(new
|
|
284
|
+
super(new D(t), e);
|
|
255
285
|
}
|
|
256
286
|
bind() {
|
|
257
287
|
this.editor.instance.addEventListener(
|
|
@@ -272,12 +302,12 @@ class y extends v {
|
|
|
272
302
|
);
|
|
273
303
|
}
|
|
274
304
|
}
|
|
275
|
-
function
|
|
276
|
-
return new
|
|
305
|
+
function V(...n) {
|
|
306
|
+
return new I(...n).bind();
|
|
277
307
|
}
|
|
278
|
-
class
|
|
308
|
+
class A {
|
|
309
|
+
instance;
|
|
279
310
|
constructor(t) {
|
|
280
|
-
o(this, "instance");
|
|
281
311
|
this.instance = t;
|
|
282
312
|
}
|
|
283
313
|
getValue() {
|
|
@@ -297,9 +327,9 @@ class P {
|
|
|
297
327
|
}), this.instance.dispatch({ selection: { anchor: e } });
|
|
298
328
|
}
|
|
299
329
|
}
|
|
300
|
-
class
|
|
330
|
+
class g extends F {
|
|
301
331
|
constructor(t, e = {}) {
|
|
302
|
-
super(new
|
|
332
|
+
super(new A(t), e);
|
|
303
333
|
}
|
|
304
334
|
bind() {
|
|
305
335
|
this.editor.instance.dom.addEventListener(
|
|
@@ -320,16 +350,16 @@ class h extends v {
|
|
|
320
350
|
);
|
|
321
351
|
}
|
|
322
352
|
}
|
|
323
|
-
function
|
|
324
|
-
return new
|
|
353
|
+
function k(...n) {
|
|
354
|
+
return new g(...n).bind();
|
|
325
355
|
}
|
|
326
|
-
function
|
|
327
|
-
return
|
|
356
|
+
function L(n = {}) {
|
|
357
|
+
return w.domEventHandlers({
|
|
328
358
|
paste: (t, e) => {
|
|
329
|
-
new
|
|
359
|
+
new g(e, n).onPaste(t);
|
|
330
360
|
},
|
|
331
361
|
drop: (t, e) => {
|
|
332
|
-
t.stopPropagation(), t.preventDefault(), new
|
|
362
|
+
t.stopPropagation(), t.preventDefault(), new g(e, n).onDrop(t);
|
|
333
363
|
},
|
|
334
364
|
dragenter: (t) => {
|
|
335
365
|
t.stopPropagation(), t.preventDefault();
|
|
@@ -340,11 +370,11 @@ function M(n = {}) {
|
|
|
340
370
|
});
|
|
341
371
|
}
|
|
342
372
|
export {
|
|
343
|
-
|
|
373
|
+
g as CodeMirrorInlineAttachmentAdapter,
|
|
344
374
|
E as DEFAULT_OPTIONS,
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
375
|
+
F as InlineAttachment,
|
|
376
|
+
I as InputInlineAttachmentAdapter,
|
|
377
|
+
V as attach,
|
|
378
|
+
k as attachCodeMirror,
|
|
379
|
+
L as inlineAttachmentExtension
|
|
350
380
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(s,h){typeof exports=="object"&&typeof module<"u"?h(exports,require("@codemirror/view")):typeof define=="function"&&define.amd?define(["exports","@codemirror/view"],h):(s=typeof globalThis<"u"?globalThis:s||self,h(s.inlineAttacher={},s.CodemirrorView))})(this,(function(s,h){"use strict";const F={uploadUrl:"/upload",uploadMethod:"POST",uploadFieldName:"file",defaultExtension:"png",responseUrlKey:"url",allowedTypes:["image/jpeg","image/png","image/jpg","image/gif"],progressText:"![Uploading file...]()",urlText:"",errorText:"Error uploading file",extraParams:{},extraHeaders:{},beforeFileUpload(){return!0},onFileReceived(){return!0},onFileUploadSucceed(){return!0},onFileUploadError(){return!0},onFileUploaded(){}};async function P({url:n,...t}){try{const e=await fetch(n,t);if(!e.ok)throw new Error(e.statusText);return{ok:!0,value:await e.json()}}catch(e){return{ok:!1,value:e}}}function T(n){return typeof n=="function"}function y(n,t="",e=""){const o=t.split(".");let i=n;for(const r of o)if(i&&typeof i=="object"&&r in i)i=i[r];else return e;return i!==void 0?i:e}function A(n,t,e,o=0){let i=0;for(let r=0;r<=o;r+=1){const a=n.indexOf(t,i);if(a===-1)return n;if(r===o)return n.slice(0,a)+e+n.slice(a+t.length);i=a+t.length}return n}class v{options=F;editor;filename="";lastValue="";pendingPlaceholders=[];constructor(t,e){this.editor=t,this.options={...F,...e}}async uploadFile(t,e){const{defaultExtension:o,remoteFilename:i,uploadFieldName:r,extraParams:a,extraHeaders:l,uploadUrl:d,uploadMethod:u,beforeFileUpload:p,uploadHandler:E}=this.options,f=new FormData,M=o.replace(/^\./,""),g=i?.(t)||t.name||`image-${Date.now()}.${M}`;if(this.filename=g,f.append(r,t,g),Object.keys(a).forEach(c=>{f.append(c,a[c])}),!p?.(f))return;if(E){try{const c=await E({file:t,filename:g,formData:f,options:this.options});this.onFileUploadSucceed(c,e,g)}catch(c){this.onFileUploadError(c instanceof Error?c:new Error(String(c)),e)}return}const{ok:L,value:w}=await P({url:d,method:u,body:f,headers:l});if(!L){this.onFileUploadError(w,e);return}this.onFileUploadSucceed(w,e,g)}isFileAllowed(t){const{allowedTypes:e}=this.options;return e.includes("*")||e.includes(t.type)}onFileUploadSucceed(t,e,o=this.filename){const{onFileUploadSucceed:i,urlText:r,responseUrlKey:a}=this.options;if(!i?.(t))return;const l=typeof e=="string"?e:e?.text||this.lastValue;if(!l)return;const d=y(t,a)||"unknown URL",u=/!\[({[^}]+})]\(([^)]+)\)/,p=T(r)?r(d,t):r.replace(r.match(u)[1],o).replace(r.match(u)[2],d),E=this.replacePlaceholder(e,l,p);this.editor.setValue(E),this.options.onFileUploaded?.(d)}onFileUploadError(t,e){if(!this.options.onFileUploadError?.(t))return;const o=typeof e=="string"?e:e?.text||this.lastValue;if(!o)return;const i=this.replacePlaceholder(e,o,this.options.errorText);this.editor.setValue(i)}onFileInserted(t){const e=this.insertFile(t);return e?e.text:!1}handleFiles(t){Array.from(t).forEach(e=>{if(!this.isFileAllowed(e))return;const o=this.pendingPlaceholders.length,i=this.onFileInserted(e);if(!i)return;const r=this.pendingPlaceholders[o];this.uploadFile(e,r?.text===i?r:i)})}insertFile(t){if(!this.options.onFileReceived?.(t))return!1;const e={id:Symbol("inline-attacher-placeholder"),text:this.options.progressText};return this.pendingPlaceholders.push(e),this.lastValue=e.text,this.editor.insertValue(e.text),e}replacePlaceholder(t,e,o){const i=this.editor.getValue();if(!t||typeof t=="string")return i.replace(e,o);const r=this.pendingPlaceholders.findIndex(({id:a})=>a===t.id);return r===-1?i.replace(e,o):(this.pendingPlaceholders.splice(r,1),A(i,e,o,r))}onPaste(t){t.clipboardData?.files.length&&this.handleFiles(t.clipboardData.files)}onDrop(t){t.dataTransfer?.files.length&&this.handleFiles(t.dataTransfer.files)}}function U(n,t){const e=n.scrollTop,o=n.selectionStart??0,i=n.selectionEnd??o,r=Math.min(o,i),a=Math.max(o,i),{value:l}=n,d=l.slice(0,r),u=l.slice(a,l.length);n.value=d+t+u;const p=r+t.length;n.selectionStart=p,n.selectionEnd=p,n.scrollTop=e,n.focus()}class I{instance;constructor(t){this.instance=t}getValue(){return this.instance.value}insertValue(t){U(this.instance,t),this.dispatchInputEvent()}setValue(t){this.instance.value=t,this.dispatchInputEvent()}dispatchInputEvent(){this.instance.dispatchEvent(new InputEvent("input",{bubbles:!0,cancelable:!0}))}}class x extends v{constructor(t,e={}){super(new I(t),e)}bind(){this.editor.instance.addEventListener("paste",t=>{this.onPaste(t)}),this.editor.instance.addEventListener("drop",t=>{t.preventDefault(),this.onDrop(t)}),this.editor.instance.addEventListener("dragover",t=>{t.preventDefault()})}}function b(...n){return new x(...n).bind()}class D{instance;constructor(t){this.instance=t}getValue(){return this.instance.state.doc.toString()}insertValue(t){this.instance.dispatch(this.instance.state.replaceSelection(t))}setValue(t){const e=this.instance.state.selection.main.head;this.instance.dispatch({changes:{from:0,to:this.instance.state.doc.length,insert:t}}),this.instance.dispatch({selection:{anchor:e}})}}class m extends v{constructor(t,e={}){super(new D(t),e)}bind(){this.editor.instance.dom.addEventListener("paste",t=>{this.onPaste(t)}),this.editor.instance.dom.addEventListener("drop",t=>{t.preventDefault(),this.onDrop(t)}),this.editor.instance.dom.addEventListener("dragover",t=>{t.preventDefault()})}}function S(...n){return new m(...n).bind()}function V(n={}){return h.EditorView.domEventHandlers({paste:(t,e)=>{new m(e,n).onPaste(t)},drop:(t,e)=>{t.stopPropagation(),t.preventDefault(),new m(e,n).onDrop(t)},dragenter:t=>{t.stopPropagation(),t.preventDefault()},dragover:t=>{t.stopPropagation(),t.preventDefault()}})}s.CodeMirrorInlineAttachmentAdapter=m,s.DEFAULT_OPTIONS=F,s.InlineAttachment=v,s.InputInlineAttachmentAdapter=x,s.attach=b,s.attachCodeMirror=S,s.inlineAttachmentExtension=V,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})}));
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
export interface UploadHandlerContext {
|
|
2
|
+
file: File;
|
|
3
|
+
filename: string;
|
|
4
|
+
formData: FormData;
|
|
5
|
+
options: InlineAttachmentOptions;
|
|
6
|
+
}
|
|
1
7
|
export interface InlineAttachmentOptions {
|
|
2
8
|
uploadUrl: string;
|
|
3
9
|
uploadMethod: string;
|
|
@@ -15,6 +21,7 @@ export interface InlineAttachmentOptions {
|
|
|
15
21
|
[name: string]: any;
|
|
16
22
|
};
|
|
17
23
|
beforeFileUpload?: (formData: FormData) => boolean;
|
|
24
|
+
uploadHandler?: (context: UploadHandlerContext) => Promise<Record<string, unknown>> | Record<string, unknown>;
|
|
18
25
|
remoteFilename?: (file: File) => string;
|
|
19
26
|
onFileReceived?: (file: File) => boolean;
|
|
20
27
|
onFileUploadSucceed?: (response: Record<string, unknown>) => boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inline-attacher",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "📎 A modern port from Inline Attachment",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -11,10 +11,23 @@
|
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
14
15
|
"import": "./dist/inline-attacher.js",
|
|
15
16
|
"require": "./dist/inline-attacher.umd.cjs"
|
|
16
17
|
}
|
|
17
18
|
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"dev": "vite",
|
|
21
|
+
"build": "rimraf dist && tsc && vite build",
|
|
22
|
+
"preview": "vite preview",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"playground:dev": "pnpm -C playground dev",
|
|
25
|
+
"playground:deploy": "pnpm -C playground run deploy",
|
|
26
|
+
"lint": "eslint --fix --ext .ts src",
|
|
27
|
+
"prepublishOnly": "pnpm build",
|
|
28
|
+
"release": "npx standard-version && git push --follow-tags && npm publish",
|
|
29
|
+
"size-check": "npx vite-bundle-visualizer"
|
|
30
|
+
},
|
|
18
31
|
"keywords": [
|
|
19
32
|
"inline-attachment",
|
|
20
33
|
"attachment",
|
|
@@ -24,7 +37,7 @@
|
|
|
24
37
|
"image",
|
|
25
38
|
"file"
|
|
26
39
|
],
|
|
27
|
-
"author": "Michael Wang
|
|
40
|
+
"author": "Michael Wang <hi@eastsun.me> (https://github.com/EastSun5566)",
|
|
28
41
|
"license": "MIT",
|
|
29
42
|
"repository": {
|
|
30
43
|
"type": "git",
|
|
@@ -34,36 +47,27 @@
|
|
|
34
47
|
"url": "https://github.com/EastSun5566/inline-attachment/issues/new"
|
|
35
48
|
},
|
|
36
49
|
"homepage": "https://github.com/EastSun5566/inline-attachment",
|
|
50
|
+
"packageManager": "pnpm@10.34.4",
|
|
37
51
|
"engines": {
|
|
38
|
-
"node": ">=
|
|
52
|
+
"node": ">=22"
|
|
39
53
|
},
|
|
40
54
|
"peerDependencies": {
|
|
41
55
|
"@codemirror/view": ">=6.0.0"
|
|
42
56
|
},
|
|
43
57
|
"devDependencies": {
|
|
44
|
-
"@codemirror/state": "^6.
|
|
45
|
-
"@
|
|
58
|
+
"@codemirror/state": "^6.7.0",
|
|
59
|
+
"@codemirror/view": "^6.43.4",
|
|
60
|
+
"@types/node": "^22.20.0",
|
|
46
61
|
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
47
62
|
"@typescript-eslint/parser": "^6.21.0",
|
|
48
63
|
"eslint": "^8.57.1",
|
|
49
64
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
50
65
|
"eslint-config-airbnb-typescript": "^17.1.0",
|
|
51
66
|
"eslint-plugin-import": "^2.31.0",
|
|
67
|
+
"happy-dom": "^20.0.2",
|
|
52
68
|
"rimraf": "^5.0.10",
|
|
53
|
-
"typescript": "^
|
|
54
|
-
"vite": "^
|
|
55
|
-
|
|
56
|
-
"dependencies": {
|
|
57
|
-
"@codemirror/view": "^6.34.1"
|
|
58
|
-
},
|
|
59
|
-
"scripts": {
|
|
60
|
-
"dev": "vite",
|
|
61
|
-
"build": "rimraf dist && tsc && vite build",
|
|
62
|
-
"preview": "vite preview",
|
|
63
|
-
"playground:dev": "pnpm -C playground dev",
|
|
64
|
-
"playground:deploy": "pnpm -C playground deploy",
|
|
65
|
-
"lint": "eslint --fix --ext .ts src",
|
|
66
|
-
"release": "pnpx standard-version && git push --follow-tags && pnpm publish && pnpm dlx jsr publish",
|
|
67
|
-
"size-check": "pnpx vite-bundle-visualizer"
|
|
69
|
+
"typescript": "^6.0.2",
|
|
70
|
+
"vite": "^7.3.0",
|
|
71
|
+
"vitest": "^4.0.16"
|
|
68
72
|
}
|
|
69
|
-
}
|
|
73
|
+
}
|