@live-change/image-frontend 0.0.3

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.
@@ -0,0 +1,438 @@
1
+
2
+ function hasAlpha(canvas) {
3
+ const context = canvas.getContext('2d')
4
+ const data = context.getImageData(0, 0, canvas.width, canvas.height).data
5
+ for (let i = 3, n = data.length; i < n; i+=4) {
6
+ if (data[i] < 255) {
7
+ return true
8
+ }
9
+ }
10
+ }
11
+
12
+ function getOrientation(jpegData) {
13
+ if(window.forceOrientation) return window.forceOrientation
14
+
15
+ let view = new DataView(jpegData)
16
+ if (view.getUint16(0, false) != 0xFFD8) return undefined
17
+ let length = view.byteLength, offset = 2
18
+ while (offset < length) {
19
+ let marker = view.getUint16(offset, false)
20
+ offset += 2
21
+ if (marker == 0xFFE1) {
22
+ if (view.getUint32(offset += 2, false) != 0x45786966) return undefined
23
+ let little = view.getUint16(offset += 6, false) == 0x4949
24
+ offset += view.getUint32(offset + 4, little)
25
+ let tags = view.getUint16(offset, little)
26
+ offset += 2
27
+ for (let i = 0; i < tags; i++)
28
+ if (view.getUint16(offset + (i * 12), little) == 0x0112)
29
+ return (view.getUint16(offset + (i * 12) + 8, little))
30
+ }
31
+ else if ((marker & 0xFF00) != 0xFF00) break;
32
+ else offset += view.getUint16(offset, false)
33
+ }
34
+ return undefined
35
+ }
36
+
37
+ function blobToDataUrl(file) {
38
+ return new Promise((resolve, reject) => {
39
+ let reader = new FileReader()
40
+ reader.onload = function(e) {
41
+ resolve(e.target.result)
42
+ }
43
+ reader.onerror = function(e) {
44
+ reject(e.target.error)
45
+ }
46
+ reader.readAsDataURL(file)
47
+ })
48
+ }
49
+
50
+ function loadImageUpload(file) {
51
+ return new Promise(function(resolve, reject) {
52
+ let img = document.createElement("img")
53
+ let reader = new FileReader()
54
+ reader.onload = async function(e) {
55
+ if(file.type == "image/jpeg") {
56
+ let headerReader = new FileReader()
57
+ headerReader.onload=function(he) {
58
+ let orientation = getOrientation(he.target.result)
59
+ img.onload = function(e) {
60
+ resolve({
61
+ image: img,
62
+ type: file.type,
63
+ orientation: orientation,
64
+ sizeSwap: orientation>4,
65
+ width: orientation>4 ? img.height : img.width,
66
+ height: orientation>4 ? img.width : img.height
67
+ })
68
+ }
69
+ img.src = e.target.result
70
+ }
71
+ headerReader.onerror = function(e) {
72
+ reject(e.target.error)
73
+ }
74
+ headerReader.readAsArrayBuffer(file.slice(0, 64 * 1024))
75
+ } else {
76
+ img.onload = function(e) {
77
+ resolve({
78
+ image: img,
79
+ type: file.type,
80
+ width: img.width,
81
+ height: img.height
82
+ })
83
+ }
84
+ img.src = e.target.result
85
+ }
86
+ }
87
+ reader.onerror = function(e) {
88
+ reject(e.target.error)
89
+ }
90
+ reader.readAsDataURL(file)
91
+ })
92
+ }
93
+
94
+ function loadImage(url) {
95
+ return new Promise((resolve, reject) => {
96
+ let image = new Image
97
+ image.onload = () => {
98
+ resolve(image)
99
+ }
100
+ image.onerror = (ev) => {
101
+ reject(ev)
102
+ }
103
+ image.src = url
104
+ })
105
+ }
106
+
107
+ function resize(img, w, h) {
108
+ let canvas=imageUtils.imageToCanvas(img)
109
+ resizeCanvas(canvas,w,h)
110
+ return canvas.toDataURL("image/jpeg",1)
111
+ }
112
+
113
+ // 0 1 2 3 4 5 6 7 8
114
+ const reverseOrientations = [0, 0, 2, 3, 4, 5, 8, 7, 6]
115
+
116
+ let exifOrientationSupportPromise = null
117
+ async function isExifOrientationSupported() {
118
+ if(!exifOrientationSupportPromise) exifOrientationSupportPromise = new Promise((resolve, reject) => {
119
+ const img = new Image()
120
+ img.onerror = function() {
121
+ resolve(false)
122
+ }
123
+ img.onload = function() {
124
+ resolve(img.width !== 2)
125
+ }
126
+ img.src = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAASUkqAAgAAAABABIBAwABAAAABgASAAAAAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAABAAIDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/iiiigD/2Q==';
127
+ })
128
+ return exifOrientationSupportPromise
129
+ }
130
+
131
+ function cancelOrientation(canvas, orientation) {
132
+ const change = reverseOrientations[orientation]
133
+ if(change) return changeOrientation(canvas, change)
134
+ return canvas
135
+ }
136
+
137
+ function changeOrientation(canvas, orientation) {
138
+ console.log("CHANGE ORIENTATION", orientation, canvas.width, canvas.height, canvas)
139
+ const w = canvas.width
140
+ const h = canvas.height
141
+ let w2 = 0
142
+ let h2 = 0
143
+ const fromIData = canvas.getContext("2d").getImageData(0, 0, w, h)
144
+ const fromData = fromIData.data
145
+ let toIData
146
+ switch(orientation) {
147
+ case 2 : {
148
+ w2=w
149
+ h2=h
150
+ canvas.width = w2
151
+ canvas.height = h2
152
+ toIData = canvas.getContext("2d").getImageData(0, 0, w2, h2)
153
+ const toData = toIData.data
154
+ for(let y=0; y<h; y++) {
155
+ for(let x=0; x<w; x++) {
156
+ const from=x+y*w
157
+ const to=(w-x-1)+y*w
158
+ toData[(to<<2)+0] = fromData[(from<<2)+0]
159
+ toData[(to<<2)+1] = fromData[(from<<2)+1]
160
+ toData[(to<<2)+2] = fromData[(from<<2)+2]
161
+ toData[(to<<2)+3] = fromData[(from<<2)+3]
162
+ }
163
+ }
164
+ } break;
165
+ case 3 : {
166
+ w2 = w
167
+ h2 = h
168
+ canvas.width = w2
169
+ canvas.height = h2
170
+ toIData = canvas.getContext("2d").getImageData(0, 0, w2, h2)
171
+ const toData = toIData.data
172
+ for (let y = 0; y < h; y++) {
173
+ for (let x = 0; x < w; x++) {
174
+ const from = (w - x - 1) + y * w
175
+ const to = x + (h - y - 1) * w
176
+ toData[(to << 2) + 0] = fromData[(from << 2) + 0]
177
+ toData[(to << 2) + 1] = fromData[(from << 2) + 1]
178
+ toData[(to << 2) + 2] = fromData[(from << 2) + 2]
179
+ toData[(to << 2) + 3] = fromData[(from << 2) + 3]
180
+ }
181
+ }
182
+ }break;
183
+ case 4 : {
184
+ w2=w
185
+ h2=h
186
+ canvas.width = w2
187
+ canvas.height = h2
188
+ toIData = canvas.getContext("2d").getImageData(0, 0, w2, h2)
189
+ const toData = toIData.data
190
+ for(let y=0; y<h; y++) {
191
+ for(let x=0; x<w; x++) {
192
+ const from = x+y*w
193
+ const to = x+(h-y-1)*w
194
+ toData[(to<<2)+0] = fromData[(from<<2)+0]
195
+ toData[(to<<2)+1] = fromData[(from<<2)+1]
196
+ toData[(to<<2)+2] = fromData[(from<<2)+2]
197
+ toData[(to<<2)+3] = fromData[(from<<2)+3]
198
+ }
199
+ }
200
+ } break;
201
+ case 5 : {
202
+ w2 = h
203
+ h2 = w
204
+ canvas.width = w2
205
+ canvas.height = h2
206
+ toIData = canvas.getContext("2d").getImageData(0, 0, w2, h2)
207
+ const toData = toIData.data
208
+ for (let y = 0; y < h; y++) {
209
+ for (let x = 0; x < w; x++) {
210
+ const from = x + y * w
211
+ const to = y + x * w2
212
+ toData[(to << 2) + 0] = fromData[(from << 2) + 0]
213
+ toData[(to << 2) + 1] = fromData[(from << 2) + 1]
214
+ toData[(to << 2) + 2] = fromData[(from << 2) + 2]
215
+ toData[(to << 2) + 3] = fromData[(from << 2) + 3]
216
+ }
217
+ }
218
+ } break;
219
+ case 6 : {
220
+ w2 = h
221
+ h2 = w
222
+ canvas.width = w2
223
+ canvas.height = h2
224
+ toIData = canvas.getContext("2d").getImageData(0, 0, w2, h2)
225
+ const toData = toIData.data
226
+ for (let y = 0; y < h; y++) {
227
+ for (let x = 0; x < w; x++) {
228
+ const from = x + y * w
229
+ const to = y + (h2 - x - 1) * w2
230
+ toData[(to << 2) + 0] = fromData[(from << 2) + 0]
231
+ toData[(to << 2) + 1] = fromData[(from << 2) + 1]
232
+ toData[(to << 2) + 2] = fromData[(from << 2) + 2]
233
+ toData[(to << 2) + 3] = fromData[(from << 2) + 3]
234
+ }
235
+ }
236
+ } break;
237
+ case 7 : {
238
+ w2 = h
239
+ h2 = w
240
+ canvas.width = w2
241
+ canvas.height = h2
242
+ toIData = canvas.getContext("2d").getImageData(0, 0, w2, h2)
243
+ const toData = toIData.data
244
+ for (let y = 0; y < h; y++) {
245
+ for (let x = 0; x < w; x++) {
246
+ const from = x + y * w
247
+ const to = (w2 - y - 1) + (h2 - x - 1) * w2
248
+ toData[(to << 2) + 0] = fromData[(from << 2) + 0]
249
+ toData[(to << 2) + 1] = fromData[(from << 2) + 1]
250
+ toData[(to << 2) + 2] = fromData[(from << 2) + 2]
251
+ toData[(to << 2) + 3] = fromData[(from << 2) + 3]
252
+ }
253
+ }
254
+ } break;
255
+ case 8 : {
256
+ w2 = h
257
+ h2 = w
258
+ canvas.width = w2
259
+ canvas.height = h2
260
+ toIData = canvas.getContext("2d").getImageData(0, 0, w2, h2)
261
+ const toData = toIData.data
262
+ for (let y = 0; y < h; y++) {
263
+ for (let x = 0; x < w; x++) {
264
+ const from = x + y * w
265
+ const to = (w2 - y - 1) + x * w2
266
+ toData[(to << 2) + 0] = fromData[(from << 2) + 0]
267
+ toData[(to << 2) + 1] = fromData[(from << 2) + 1]
268
+ toData[(to << 2) + 2] = fromData[(from << 2) + 2]
269
+ toData[(to << 2) + 3] = fromData[(from << 2) + 3]
270
+ }
271
+ }
272
+ } break;
273
+ default: {
274
+ w2 = w
275
+ h2 = h
276
+ canvas.width = w2
277
+ canvas.height = h2
278
+ toIData = canvas.getContext("2d").getImageData(0, 0, w2, h2)
279
+ const toData = toIData.data
280
+ for (let y = 0; y < h; y++) {
281
+ for (let x = 0; x < w; x++) {
282
+ const from = x + y * w
283
+ const to = x + y * w
284
+ toData[(to << 2) + 0] = fromData[(from << 2) + 0]
285
+ toData[(to << 2) + 1] = fromData[(from << 2) + 1]
286
+ toData[(to << 2) + 2] = fromData[(from << 2) + 2]
287
+ toData[(to << 2) + 3] = fromData[(from << 2) + 3]
288
+ }
289
+ }
290
+ } break;
291
+ }
292
+
293
+ canvas.getContext("2d").putImageData(toIData, 0, 0)
294
+ return canvas
295
+ }
296
+
297
+ function imageToCanvas(image) {
298
+ const canvas= document.createElement("canvas")
299
+ canvas.width = image.width
300
+ canvas.height = image.height
301
+ const ctx = canvas.getContext("2d")
302
+ ctx.save()
303
+ ctx.drawImage(image, 0, 0)
304
+ return canvas
305
+ }
306
+
307
+ function resizeCanvas(canvas, w, h) {
308
+ const img = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height)
309
+ const img2 = canvas.getContext("2d").getImageData(0, 0, w, h)
310
+ const inputData = img.data
311
+ const outputData = img2.data
312
+ resampleHermite(inputData, canvas.width, canvas.height, outputData, w, h)
313
+ canvas.getContext("2d").clearRect(0, 0, Math.max(canvas.width, w), Math.max(canvas.height, h))
314
+ canvas.width = w
315
+ canvas.height = h
316
+ canvas.getContext("2d").putImageData(img2, 0, 0);
317
+ }
318
+
319
+ function cropCanvas(canvas, x, y, w, h) {
320
+ const img = canvas.getContext("2d").getImageData(x, y, w, h)
321
+ canvas.width=w
322
+ canvas.height=h
323
+ canvas.getContext("2d").putImageData(img, 0, 0)
324
+ }
325
+
326
+ function resampleHermite(src, w, h, dest, w2, h2){
327
+ const startTime = Date.now()
328
+ const ratio_w = w / w2
329
+ const ratio_h = h / h2
330
+ const ratio_w_half = Math.ceil(ratio_w/2)
331
+ const ratio_h_half = Math.ceil(ratio_h/2)
332
+
333
+ for(let j = 0; j < h2; j++){
334
+ for(let i = 0; i < w2; i++){
335
+ const x2 = (i + j*w2) * 4;
336
+ const center_y = (j + 0.5) * ratio_h
337
+
338
+ let weight = 0;
339
+ let weights = 0;
340
+ let weights_alpha = 0;
341
+ let gx_r = 0
342
+ let gx_g = 0
343
+ let gx_b = 0
344
+ let gx_a = 0
345
+
346
+ for(let yy = Math.floor(j * ratio_h); yy < (j + 1) * ratio_h; yy++){
347
+ const dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half
348
+ const center_x = (i + 0.5) * ratio_w
349
+ const f0 = dy*dy //pre-calc part of f
350
+ for(let xx = Math.floor(i * ratio_w); xx < (i + 1) * ratio_w; xx++){
351
+ let dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half
352
+ const f = Math.sqrt(f0 + dx*dx)
353
+ if(f >= -1 && f <= 1){
354
+ //hermite filter
355
+ weight = 2 * f*f*f - 3*f*f + 1
356
+ if(weight > 0){
357
+ dx = 4*(xx + yy*f)
358
+ //alpha
359
+ gx_a += weight * src[dx + 3]
360
+ weights_alpha += weight
361
+ //colors
362
+ if(src[dx + 3] < 255)
363
+ weight = weight * src[dx + 3] / 250
364
+ gx_r += weight * src[dx]
365
+ gx_g += weight * src[dx + 1]
366
+ gx_b += weight * src[dx + 2]
367
+ weights += weight
368
+ }
369
+ }
370
+ }
371
+ }
372
+ dest[x2] = gx_r / weights
373
+ dest[x2 + 1] = gx_g / weights
374
+ dest[x2 + 2] = gx_b / weights
375
+ dest[x2 + 3] = gx_a / weights_alpha
376
+ }
377
+ }
378
+ console.log(`hermite resample took ${Date.now() - startTime}ms`)
379
+
380
+ }
381
+
382
+ function getDataURIData(dataURI) {
383
+ // convert base64/URLEncoded data component to raw binary data held in a string
384
+ let byteString
385
+ if (dataURI.split(',')[0].indexOf('base64') >= 0)
386
+ byteString = atob(dataURI.split(',')[1])
387
+ else
388
+ byteString = unescape(dataURI.split(',')[1])
389
+ // write the bytes of the string to a typed array
390
+ let ia = new Uint8Array(byteString.length)
391
+ for (let i = 0; i < byteString.length; i++) {
392
+ ia[i] = byteString.charCodeAt(i)
393
+ }
394
+ return ia
395
+ }
396
+
397
+ function getDataURIMime(dataURI) {
398
+ return dataURI.split(',')[0].split(':')[1].split(';')[0]
399
+ }
400
+
401
+
402
+ const methods = {
403
+ getOrientation,
404
+ loadImageUpload,
405
+ resize,
406
+ changeOrientation,
407
+ cancelOrientation,
408
+ imageToCanvas,
409
+ resizeCanvas,
410
+ cropCanvas,
411
+ resampleHermite,
412
+ getDataURIData,
413
+ getDataURIMime,
414
+ blobToDataUrl,
415
+ hasAlpha,
416
+ isExifOrientationSupported,
417
+ loadImage
418
+ }
419
+
420
+ export {
421
+ getOrientation,
422
+ loadImageUpload,
423
+ resize,
424
+ changeOrientation,
425
+ cancelOrientation,
426
+ imageToCanvas,
427
+ resizeCanvas,
428
+ cropCanvas,
429
+ resampleHermite,
430
+ getDataURIData,
431
+ getDataURIMime,
432
+ blobToDataUrl,
433
+ hasAlpha,
434
+ isExifOrientationSupported,
435
+ loadImage
436
+ }
437
+
438
+ export default methods
@@ -0,0 +1,122 @@
1
+ import {
2
+ imageToCanvas, loadImageUpload, cancelOrientation, hasAlpha, isExifOrientationSupported
3
+ } from "./imageUtils.js"
4
+ import imageResizer from "./imageResizer"
5
+
6
+ async function preProcessImageFile({ file, image, canvas }, config) {
7
+
8
+ const {
9
+ maxUploadSize = 10 * 1024 * 1024,
10
+ maxUploadWidth = 2048,
11
+ maxUploadHeight = 2048,
12
+ maxProcessableSize = 50 * 1024 * 1025,
13
+ maxProcessableWidth = 10000,
14
+ maxProcessableHeight = 10000,
15
+ maxProcessablePixels = 6000 * 6000
16
+ } = config
17
+
18
+ if(!file && !image && !canvas) {
19
+ throw new Error('noImage')
20
+ }
21
+
22
+ if (file?.size > maxProcessableSize) {
23
+ throw new Error("tooBig")
24
+ }
25
+
26
+ if(!image) {
27
+ if(canvas) {
28
+ image = {
29
+ width: canvas.width,
30
+ height: canvas.height,
31
+ orientation: 0,
32
+ type: config.fileType || 'image/png',
33
+ image: null // not needed because we have canvas
34
+ }
35
+ } else {
36
+ image = await loadImageUpload(file)
37
+ }
38
+ }
39
+
40
+ if (image.width > maxProcessableWidth
41
+ || image.height > maxProcessableHeight
42
+ || (image.width * image.height) > maxProcessablePixels) {
43
+ throw new Error("tooBig")
44
+ }
45
+
46
+ let processingNeeded =
47
+ image.width > maxUploadWidth
48
+ || image.height > maxUploadHeight
49
+ || image.orientation
50
+
51
+ if(!processingNeeded) {
52
+ if(!file) {
53
+ if(!canvas) canvas = imageToCanvas(image.image)
54
+ file = await new Promise(
55
+ (resolve, reject) => canvas.toBlob(resolve, config.fileType || 'image/png')
56
+ )
57
+ }
58
+ }
59
+
60
+ processingNeeded ||= file.size > maxUploadSize
61
+
62
+ if(!processingNeeded) {
63
+ return {
64
+ blob: file, canvas,
65
+ size: { width: image.width, height: image.height }
66
+ }
67
+ }
68
+
69
+ if(!canvas) canvas = imageToCanvas(image.image)
70
+
71
+ if(image.width > maxUploadWidth || image.height > maxUploadHeight ) { /// RESIZING NEEDED
72
+ const maxRatio = maxUploadWidth / maxUploadHeight
73
+ const inputRatio = image.width / image.height
74
+
75
+ let targetWidth, targetHeight
76
+ if(inputRatio > maxRatio) { /// scale to max width
77
+ targetWidth = maxUploadWidth
78
+ targetHeight = Math.round(maxUploadWidth / inputRatio)
79
+ } else { /// scale to max height
80
+ targetWidth = Math.round(maxUploadHeight * inputRatio)
81
+ targetHeight = maxUploadHeight
82
+ }
83
+
84
+ console.log(`RESIZING ${image.width}x${image.height} => ${targetWidth}x${targetHeight}`)
85
+
86
+ let destCanvas = document.createElement('canvas')
87
+ if(image.orientation > 4 && !(await isExifOrientationSupported())) { // Swap dimmensions
88
+ destCanvas.width = targetHeight
89
+ destCanvas.height = targetWidth
90
+ } else {
91
+ destCanvas.width = targetWidth
92
+ destCanvas.height = targetHeight
93
+ }
94
+ await imageResizer.resize(canvas, destCanvas, {
95
+ unsharpAmount: 80,
96
+ unsharpRadius: 0.6,
97
+ unsharpThreshold: 2,
98
+ alpha: hasAlpha(canvas)
99
+ })
100
+ canvas = destCanvas
101
+ }
102
+
103
+ if(image.orientation && !(await isExifOrientationSupported())) {
104
+ console.log("CANCEL ORIENTATION", image.orientation)
105
+ canvas = cancelOrientation(canvas, image.orientation)
106
+ }
107
+
108
+ const blob = await new Promise(
109
+ (resolve, reject) => canvas.toBlob(resolve, file?.type || config.fileType || 'image/png')
110
+ )
111
+ console.log("OUTPUT CANVAS", canvas.width, canvas.height)
112
+ console.log("OUTPUT BLOB", blob)
113
+ blob.name = file.name
114
+
115
+ return {
116
+ blob, canvas,
117
+ size: { width: canvas.width, height: canvas.height }
118
+ }
119
+
120
+ }
121
+
122
+ export default preProcessImageFile
@@ -0,0 +1,41 @@
1
+ import {
2
+ createMemoryHistory,
3
+ createRouter as _createRouter,
4
+ createWebHistory
5
+ } from 'vue-router'
6
+
7
+ import { dbAdminRoutes } from "@live-change/db-admin"
8
+
9
+ export function wysiwygRoutes(config = {}) {
10
+ const { prefix = '/', route = (r) => r } = config
11
+ return [
12
+ route({
13
+ name: 'upload:test', path: prefix + 'upload', meta: { },
14
+ component: () => import("./UploadTest.vue"),
15
+ props: {
16
+ }
17
+ }),
18
+ route({
19
+ name: 'editor:test', path: prefix + '', meta: { },
20
+ component: () => import("./EditorTest.vue"),
21
+ props: {
22
+ }
23
+ }),
24
+
25
+ ...dbAdminRoutes({ prefix: '/_db', route: r => ({ ...r, meta: { ...r.meta, raw: true }}) })
26
+ ]
27
+ }
28
+
29
+ export async function sitemap(route, api) {
30
+
31
+ }
32
+
33
+
34
+ export function createRouter(app, config) {
35
+ const router = _createRouter({
36
+ history: import.meta.env.SSR ? createMemoryHistory() : createWebHistory(),
37
+ routes: wysiwygRoutes(config)
38
+ })
39
+ return router
40
+ }
41
+
@@ -0,0 +1,18 @@
1
+ import { defineConfig } from 'vite'
2
+
3
+ import baseViteConfig from '@live-change/frontend-base/vite-config.js'
4
+
5
+ export default defineConfig(async ({ command, mode }) => {
6
+ const baseConfig = (await baseViteConfig({ command, mode }))
7
+ return {
8
+ ...baseConfig,
9
+
10
+ resolve: {
11
+ alias: [
12
+ ...baseConfig.resolve.alias,
13
+ /* { find: 'vue', replacement: 'vue/dist/vue.esm-bundler.js' },
14
+ { find: 'vue/server-renderer', replacement: 'vue/server-renderer' },*/
15
+ ]
16
+ }
17
+ }
18
+ })
package/index.js ADDED
@@ -0,0 +1,7 @@
1
+ import ImageUpload from "./front/src/ImageUpload.js"
2
+ import ImageEditor from "./front/src/ImageEditor.vue"
3
+ import Image from "./front/src/Image.vue"
4
+ import {uploadImage, imageUploads} from "./front/src/imageUploads.js";
5
+ import preProcessImageFile from "./front/src/preprocessImageFile.js";
6
+
7
+ export { ImageUpload, Image, uploadImage, preProcessImageFile, imageUploads, ImageEditor }
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@live-change/image-frontend",
3
+ "version": "0.0.3",
4
+ "scripts": {
5
+ "memDev": "lcli memDev --enableSessions --initScript ./init.js --dbAccess",
6
+ "localDevInit": "rm tmp.db; lcli localDev --enableSessions --initScript ./init.js",
7
+ "localDev": "lcli localDev --enableSessions",
8
+ "dev": "lcli dev --enableSessions",
9
+ "ssrDev": "lcli ssrDev --enableSessions",
10
+ "serveAllMem": "cross-env NODE_ENV=production lcli ssrServer --withApi --withServices --updateServices --enableSessions --withDb --dbBackend mem --createDb",
11
+ "serveAll": "cross-env NODE_ENV=production lcli ssrServer --withApi --withServices --updateServices --enableSessions",
12
+ "serve": "cross-env NODE_ENV=production lcli ssrServer --enableSessions",
13
+ "apiServer": "lcli apiServer --enableSessions",
14
+ "devApiServer": "lcli devApiServer --enableSessions",
15
+ "memApiServer": "lcli memApiServer --enableSessions",
16
+ "build": "cd front; yarn build:client && yarn build:server",
17
+ "build:client": "cd front; vite build --ssrManifest --outDir dist/client",
18
+ "build:server": "cd front; vite build --ssr src/entry-server.js --outDir dist/server",
19
+ "generate": "vite build --ssrManifest --outDir dist/static && yarn build:server && node prerender",
20
+ "debug": "node --inspect-brk server"
21
+ },
22
+ "dependencies": {
23
+ "@live-change/framework": "0.6.5",
24
+ "@live-change/cli": "0.6.5",
25
+ "@live-change/dao": "0.4.13",
26
+ "@live-change/dao-vue3": "0.4.13",
27
+ "@live-change/dao-websocket": "0.4.13",
28
+ "@live-change/vue3-ssr": "0.2.14",
29
+ "@live-change/vue3-components": "0.2.12",
30
+ "@live-change/session-service": "0.2.39",
31
+ "@live-change/image-service": "0.2.37",
32
+ "@vitejs/plugin-vue": "^2.3.1",
33
+ "@vitejs/plugin-vue-jsx": "^1.3.10",
34
+ "@vue/compiler-sfc": "^3.2.33",
35
+ "@vueuse/core": "^8.3.1",
36
+ "v-shared-element": "3.1.0",
37
+ "vue3-scroll-border": "0.1.2",
38
+ "codeceptjs-assert": "^0.0.5",
39
+ "compression": "^1.7.4",
40
+ "cross-env": "^7.0.3",
41
+ "get-port-sync": "1.0.1",
42
+ "primeicons": "^5.0.0",
43
+ "primevue": "^3.15.0",
44
+ "primeflex": "^3.2.1",
45
+ "rollup-plugin-node-builtins": "^2.1.2",
46
+ "serialize-javascript": "^6.0.0",
47
+ "serve-static": "^1.15.0",
48
+ "vite": "^2.9.6",
49
+ "vue": "^3.2.33",
50
+ "vue-meta": "^3.0.0-alpha.9",
51
+ "vue-router": "^4.0.14",
52
+ "vite-plugin-compression": "0.5.1",
53
+ "vite-plugin-vue-images": "^0.6.1",
54
+ "rollup-plugin-visualizer": "5.6.0",
55
+ "@tiptap/vue-3": "2.0.0-beta.91",
56
+ "@tiptap/starter-kit": "^2.0.0-beta.185",
57
+ "@tiptap/extension-underline": "2.0.0-beta.23",
58
+ "@tiptap/extension-highlight": "^2.0.0-beta.33",
59
+ "@fortawesome/fontawesome-free": "^6.1.1",
60
+ "pretty-bytes": "^6.0.0",
61
+ "pica": "^9.0.1"
62
+ },
63
+ "devDependencies": {
64
+ "@live-change/codeceptjs-helper": "0.6.5",
65
+ "@wdio/selenium-standalone-service": "^7.19.5",
66
+ "codeceptjs": "^3.3.1",
67
+ "playwright": "^1.21.1",
68
+ "random-profile-generator": "^2.3.0",
69
+ "txtgen": "^3.0.1",
70
+ "generate-password": "1.7.0",
71
+ "webdriverio": "^7.19.5"
72
+ },
73
+ "author": "",
74
+ "license": "ISC",
75
+ "description": ""
76
+ }