js-draw 1.13.1 → 1.13.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/dist/bundle.js +1 -1
- package/dist/cjs/Editor.js +2 -2
- package/dist/cjs/toolbar/widgets/InsertImageWidget.js +11 -4
- package/dist/cjs/util/fileToBase64Url.d.ts +9 -0
- package/dist/cjs/util/fileToBase64Url.js +39 -0
- package/dist/cjs/util/fileToBase64Url.test.d.ts +1 -0
- package/dist/cjs/version.js +1 -1
- package/dist/mjs/Editor.mjs +2 -2
- package/dist/mjs/toolbar/widgets/InsertImageWidget.mjs +11 -4
- package/dist/mjs/util/fileToBase64Url.d.ts +9 -0
- package/dist/mjs/util/fileToBase64Url.mjs +37 -0
- package/dist/mjs/util/fileToBase64Url.test.d.ts +1 -0
- package/dist/mjs/version.mjs +1 -1
- package/package.json +2 -2
- package/dist/cjs/util/fileToBase64.d.ts +0 -3
- package/dist/cjs/util/fileToBase64.js +0 -15
- package/dist/mjs/util/fileToBase64.d.ts +0 -3
- package/dist/mjs/util/fileToBase64.mjs +0 -13
package/dist/cjs/Editor.js
CHANGED
@@ -42,7 +42,7 @@ const getLocalizationTable_1 = __importDefault(require("./localizations/getLocal
|
|
42
42
|
const IconProvider_1 = __importDefault(require("./toolbar/IconProvider"));
|
43
43
|
const CanvasRenderer_1 = __importDefault(require("./rendering/renderers/CanvasRenderer"));
|
44
44
|
const untilNextAnimationFrame_1 = __importDefault(require("./util/untilNextAnimationFrame"));
|
45
|
-
const
|
45
|
+
const fileToBase64Url_1 = __importDefault(require("./util/fileToBase64Url"));
|
46
46
|
const uniteCommands_1 = __importDefault(require("./commands/uniteCommands"));
|
47
47
|
const SelectionTool_1 = __importDefault(require("./tools/SelectionTool/SelectionTool"));
|
48
48
|
const Erase_1 = __importDefault(require("./commands/Erase"));
|
@@ -476,7 +476,7 @@ class Editor {
|
|
476
476
|
this.showLoadingWarning(evt.loaded / evt.total);
|
477
477
|
};
|
478
478
|
try {
|
479
|
-
const data = await (0,
|
479
|
+
const data = await (0, fileToBase64Url_1.default)(file, { onprogress });
|
480
480
|
if (data && this.toolController.dispatchInputEvent({
|
481
481
|
kind: inputEvents_1.InputEvtType.PasteEvent,
|
482
482
|
mime: fileType,
|
@@ -9,7 +9,7 @@ const EditorImage_1 = __importDefault(require("../../image/EditorImage"));
|
|
9
9
|
const uniteCommands_1 = __importDefault(require("../../commands/uniteCommands"));
|
10
10
|
const SelectionTool_1 = __importDefault(require("../../tools/SelectionTool/SelectionTool"));
|
11
11
|
const math_1 = require("@js-draw/math");
|
12
|
-
const
|
12
|
+
const fileToBase64Url_1 = __importDefault(require("../../util/fileToBase64Url"));
|
13
13
|
const BaseWidget_1 = __importDefault(require("./BaseWidget"));
|
14
14
|
const types_1 = require("../../types");
|
15
15
|
const constants_1 = require("../constants");
|
@@ -111,11 +111,13 @@ class InsertImageWidget extends BaseWidget_1.default {
|
|
111
111
|
this.imagePreview.style.display = 'block';
|
112
112
|
const image = files[0];
|
113
113
|
let data = null;
|
114
|
+
let errorMessage = null;
|
114
115
|
try {
|
115
|
-
data = await (0,
|
116
|
+
data = await (0, fileToBase64Url_1.default)(image);
|
116
117
|
}
|
117
|
-
catch (
|
118
|
-
|
118
|
+
catch (error) {
|
119
|
+
console.error('Image load error', error);
|
120
|
+
errorMessage = this.localizationTable.imageLoadError(error);
|
119
121
|
}
|
120
122
|
if (data) {
|
121
123
|
this.image = ImageWrapper.fromSrcAndPreview(data, this.imagePreview, () => this.onImageDataUpdate());
|
@@ -124,6 +126,11 @@ class InsertImageWidget extends BaseWidget_1.default {
|
|
124
126
|
this.image = null;
|
125
127
|
}
|
126
128
|
this.onImageDataUpdate();
|
129
|
+
// Show the error after image update callbacks to ensure it is
|
130
|
+
// actually shown.
|
131
|
+
if (errorMessage) {
|
132
|
+
this.statusView.innerText = errorMessage;
|
133
|
+
}
|
127
134
|
});
|
128
135
|
altTextRow.replaceChildren(imageAltTextLabel, this.imageAltTextInput);
|
129
136
|
actionButtonRow.replaceChildren(this.submitButton);
|
@@ -0,0 +1,9 @@
|
|
1
|
+
export interface FileToBase64UrlOptions {
|
2
|
+
onprogress?: (evt: ProgressEvent<FileReader>) => void;
|
3
|
+
onWarning?: (message: string, error: any) => void;
|
4
|
+
}
|
5
|
+
/**
|
6
|
+
* Converts `file` to a base64 data URL.
|
7
|
+
*/
|
8
|
+
declare const fileToBase64Url: (file: Blob, options?: FileToBase64UrlOptions) => Promise<string | null>;
|
9
|
+
export default fileToBase64Url;
|
@@ -0,0 +1,39 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
/**
|
4
|
+
* Converts `file` to a base64 data URL.
|
5
|
+
*/
|
6
|
+
const fileToBase64Url = async (file, options = {}) => {
|
7
|
+
try {
|
8
|
+
const reader = new FileReader();
|
9
|
+
return await new Promise((resolve, reject) => {
|
10
|
+
reader.onload = () => resolve(reader.result);
|
11
|
+
reader.onerror = reject;
|
12
|
+
reader.onabort = reject;
|
13
|
+
reader.onprogress = (evt) => {
|
14
|
+
options.onprogress?.(evt);
|
15
|
+
};
|
16
|
+
reader.readAsDataURL(file);
|
17
|
+
});
|
18
|
+
}
|
19
|
+
catch (error) {
|
20
|
+
// Files can fail to load with a FileReader in some cases. For example,
|
21
|
+
// in iOS Lockdown mode, where FileReader is unavailable.
|
22
|
+
(options.onWarning ?? console.warn)('Unable to convert file to base64 with a FileReader: ', error);
|
23
|
+
const arrayBuffer = await file.arrayBuffer();
|
24
|
+
const array = new Uint8Array(arrayBuffer);
|
25
|
+
// step: must be divisible by 3 (3 bytes = 4 base64 numerals)
|
26
|
+
// If too large, this will fail (String.fromCharCode accepts a limited
|
27
|
+
// number of arguments).
|
28
|
+
const step = 30;
|
29
|
+
const result = [];
|
30
|
+
for (let i = 0; i < array.length; i += step) {
|
31
|
+
// btoa accepts only characters with byte value 0-255 (which can be created
|
32
|
+
// with String.fromCharCode)
|
33
|
+
const stringByteArray = String.fromCharCode(...array.slice(i, i + step));
|
34
|
+
result.push(btoa(stringByteArray));
|
35
|
+
}
|
36
|
+
return `data:${file.type ?? 'image/*'};base64,${result.join('')}`;
|
37
|
+
}
|
38
|
+
};
|
39
|
+
exports.default = fileToBase64Url;
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
package/dist/cjs/version.js
CHANGED
package/dist/mjs/Editor.mjs
CHANGED
@@ -13,7 +13,7 @@ import getLocalizationTable from './localizations/getLocalizationTable.mjs';
|
|
13
13
|
import IconProvider from './toolbar/IconProvider.mjs';
|
14
14
|
import CanvasRenderer from './rendering/renderers/CanvasRenderer.mjs';
|
15
15
|
import untilNextAnimationFrame from './util/untilNextAnimationFrame.mjs';
|
16
|
-
import
|
16
|
+
import fileToBase64Url from './util/fileToBase64Url.mjs';
|
17
17
|
import uniteCommands from './commands/uniteCommands.mjs';
|
18
18
|
import SelectionTool from './tools/SelectionTool/SelectionTool.mjs';
|
19
19
|
import Erase from './commands/Erase.mjs';
|
@@ -447,7 +447,7 @@ export class Editor {
|
|
447
447
|
this.showLoadingWarning(evt.loaded / evt.total);
|
448
448
|
};
|
449
449
|
try {
|
450
|
-
const data = await
|
450
|
+
const data = await fileToBase64Url(file, { onprogress });
|
451
451
|
if (data && this.toolController.dispatchInputEvent({
|
452
452
|
kind: InputEvtType.PasteEvent,
|
453
453
|
mime: fileType,
|
@@ -4,7 +4,7 @@ import EditorImage from '../../image/EditorImage.mjs';
|
|
4
4
|
import uniteCommands from '../../commands/uniteCommands.mjs';
|
5
5
|
import SelectionTool from '../../tools/SelectionTool/SelectionTool.mjs';
|
6
6
|
import { Mat33 } from '@js-draw/math';
|
7
|
-
import
|
7
|
+
import fileToBase64Url from '../../util/fileToBase64Url.mjs';
|
8
8
|
import BaseWidget from './BaseWidget.mjs';
|
9
9
|
import { EditorEventType } from '../../types.mjs';
|
10
10
|
import { toolbarCSSPrefix } from '../constants.mjs';
|
@@ -106,11 +106,13 @@ class InsertImageWidget extends BaseWidget {
|
|
106
106
|
this.imagePreview.style.display = 'block';
|
107
107
|
const image = files[0];
|
108
108
|
let data = null;
|
109
|
+
let errorMessage = null;
|
109
110
|
try {
|
110
|
-
data = await
|
111
|
+
data = await fileToBase64Url(image);
|
111
112
|
}
|
112
|
-
catch (
|
113
|
-
|
113
|
+
catch (error) {
|
114
|
+
console.error('Image load error', error);
|
115
|
+
errorMessage = this.localizationTable.imageLoadError(error);
|
114
116
|
}
|
115
117
|
if (data) {
|
116
118
|
this.image = ImageWrapper.fromSrcAndPreview(data, this.imagePreview, () => this.onImageDataUpdate());
|
@@ -119,6 +121,11 @@ class InsertImageWidget extends BaseWidget {
|
|
119
121
|
this.image = null;
|
120
122
|
}
|
121
123
|
this.onImageDataUpdate();
|
124
|
+
// Show the error after image update callbacks to ensure it is
|
125
|
+
// actually shown.
|
126
|
+
if (errorMessage) {
|
127
|
+
this.statusView.innerText = errorMessage;
|
128
|
+
}
|
122
129
|
});
|
123
130
|
altTextRow.replaceChildren(imageAltTextLabel, this.imageAltTextInput);
|
124
131
|
actionButtonRow.replaceChildren(this.submitButton);
|
@@ -0,0 +1,9 @@
|
|
1
|
+
export interface FileToBase64UrlOptions {
|
2
|
+
onprogress?: (evt: ProgressEvent<FileReader>) => void;
|
3
|
+
onWarning?: (message: string, error: any) => void;
|
4
|
+
}
|
5
|
+
/**
|
6
|
+
* Converts `file` to a base64 data URL.
|
7
|
+
*/
|
8
|
+
declare const fileToBase64Url: (file: Blob, options?: FileToBase64UrlOptions) => Promise<string | null>;
|
9
|
+
export default fileToBase64Url;
|
@@ -0,0 +1,37 @@
|
|
1
|
+
/**
|
2
|
+
* Converts `file` to a base64 data URL.
|
3
|
+
*/
|
4
|
+
const fileToBase64Url = async (file, options = {}) => {
|
5
|
+
try {
|
6
|
+
const reader = new FileReader();
|
7
|
+
return await new Promise((resolve, reject) => {
|
8
|
+
reader.onload = () => resolve(reader.result);
|
9
|
+
reader.onerror = reject;
|
10
|
+
reader.onabort = reject;
|
11
|
+
reader.onprogress = (evt) => {
|
12
|
+
options.onprogress?.(evt);
|
13
|
+
};
|
14
|
+
reader.readAsDataURL(file);
|
15
|
+
});
|
16
|
+
}
|
17
|
+
catch (error) {
|
18
|
+
// Files can fail to load with a FileReader in some cases. For example,
|
19
|
+
// in iOS Lockdown mode, where FileReader is unavailable.
|
20
|
+
(options.onWarning ?? console.warn)('Unable to convert file to base64 with a FileReader: ', error);
|
21
|
+
const arrayBuffer = await file.arrayBuffer();
|
22
|
+
const array = new Uint8Array(arrayBuffer);
|
23
|
+
// step: must be divisible by 3 (3 bytes = 4 base64 numerals)
|
24
|
+
// If too large, this will fail (String.fromCharCode accepts a limited
|
25
|
+
// number of arguments).
|
26
|
+
const step = 30;
|
27
|
+
const result = [];
|
28
|
+
for (let i = 0; i < array.length; i += step) {
|
29
|
+
// btoa accepts only characters with byte value 0-255 (which can be created
|
30
|
+
// with String.fromCharCode)
|
31
|
+
const stringByteArray = String.fromCharCode(...array.slice(i, i + step));
|
32
|
+
result.push(btoa(stringByteArray));
|
33
|
+
}
|
34
|
+
return `data:${file.type ?? 'image/*'};base64,${result.join('')}`;
|
35
|
+
}
|
36
|
+
};
|
37
|
+
export default fileToBase64Url;
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
package/dist/mjs/version.mjs
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "js-draw",
|
3
|
-
"version": "1.13.
|
3
|
+
"version": "1.13.2",
|
4
4
|
"description": "Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript. ",
|
5
5
|
"types": "./dist/mjs/lib.d.ts",
|
6
6
|
"main": "./dist/cjs/lib.js",
|
@@ -86,5 +86,5 @@
|
|
86
86
|
"freehand",
|
87
87
|
"svg"
|
88
88
|
],
|
89
|
-
"gitHead": "
|
89
|
+
"gitHead": "9a48e4d746783977e2b2808be9d97f3521fb830f"
|
90
90
|
}
|
@@ -1,15 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const fileToBase64 = (file, onprogress) => {
|
4
|
-
const reader = new FileReader();
|
5
|
-
return new Promise((resolve, reject) => {
|
6
|
-
reader.onload = () => resolve(reader.result);
|
7
|
-
reader.onerror = reject;
|
8
|
-
reader.onabort = reject;
|
9
|
-
reader.onprogress = (evt) => {
|
10
|
-
onprogress?.(evt);
|
11
|
-
};
|
12
|
-
reader.readAsDataURL(file);
|
13
|
-
});
|
14
|
-
};
|
15
|
-
exports.default = fileToBase64;
|
@@ -1,13 +0,0 @@
|
|
1
|
-
const fileToBase64 = (file, onprogress) => {
|
2
|
-
const reader = new FileReader();
|
3
|
-
return new Promise((resolve, reject) => {
|
4
|
-
reader.onload = () => resolve(reader.result);
|
5
|
-
reader.onerror = reject;
|
6
|
-
reader.onabort = reject;
|
7
|
-
reader.onprogress = (evt) => {
|
8
|
-
onprogress?.(evt);
|
9
|
-
};
|
10
|
-
reader.readAsDataURL(file);
|
11
|
-
});
|
12
|
-
};
|
13
|
-
export default fileToBase64;
|