mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 19:57:52 +01:00
editor: fix loading of images that have wrong mime type
This commit is contained in:
committed by
Abdullah Atta
parent
95666bee36
commit
a442677e91
@@ -416,7 +416,6 @@ export function Editor(props: EditorProps) {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
onGetAttachmentData={(attachment) => {
|
onGetAttachmentData={(attachment) => {
|
||||||
console.log("ID", id);
|
|
||||||
return downloadAttachment(
|
return downloadAttachment(
|
||||||
attachment.hash,
|
attachment.hash,
|
||||||
attachment.type === "web-clip" ? "text" : "base64",
|
attachment.type === "web-clip" ? "text" : "base64",
|
||||||
|
|||||||
82
packages/core/package-lock.json
generated
82
packages/core/package-lock.json
generated
@@ -12,6 +12,7 @@
|
|||||||
"@microsoft/signalr": "^7.0.10",
|
"@microsoft/signalr": "^7.0.10",
|
||||||
"@microsoft/signalr-protocol-msgpack": "^7.0.10",
|
"@microsoft/signalr-protocol-msgpack": "^7.0.10",
|
||||||
"@notesnook/logger": "file:../logger",
|
"@notesnook/logger": "file:../logger",
|
||||||
|
"@readme/data-urls": "^3.0.0",
|
||||||
"@streetwriters/showdown": "^3.0.2-alpha",
|
"@streetwriters/showdown": "^3.0.2-alpha",
|
||||||
"async-mutex": "^0.3.2",
|
"async-mutex": "^0.3.2",
|
||||||
"dayjs": "1.11.9",
|
"dayjs": "1.11.9",
|
||||||
@@ -576,6 +577,14 @@
|
|||||||
"@otplib/plugin-thirty-two": "^12.0.1"
|
"@otplib/plugin-thirty-two": "^12.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@readme/data-urls": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@readme/data-urls/-/data-urls-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-b0L7VWqbLZqOSSAFUrxS5ZwUfec35WDsAwwCH481vYnhk0dWO3nvmNVNCbP8CY4cXqwL1W4uCAnhDz+CUmXM3g==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@selderee/plugin-htmlparser2": {
|
"node_modules/@selderee/plugin-htmlparser2": {
|
||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
|
||||||
@@ -1176,20 +1185,6 @@
|
|||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/data-urls": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"abab": "^2.0.6",
|
|
||||||
"whatwg-mimetype": "^3.0.0",
|
|
||||||
"whatwg-url": "^12.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/dayjs": {
|
"node_modules/dayjs": {
|
||||||
"version": "1.11.9",
|
"version": "1.11.9",
|
||||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
|
||||||
@@ -1788,6 +1783,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jsdom/node_modules/data-urls": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"abab": "^2.0.6",
|
||||||
|
"whatwg-mimetype": "^3.0.0",
|
||||||
|
"whatwg-url": "^12.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jsdom/node_modules/ws": {
|
"node_modules/jsdom/node_modules/ws": {
|
||||||
"version": "8.13.0",
|
"version": "8.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||||
@@ -2269,9 +2278,9 @@
|
|||||||
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
|
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
|
||||||
},
|
},
|
||||||
"node_modules/punycode": {
|
"node_modules/punycode": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
|
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
@@ -3253,6 +3262,11 @@
|
|||||||
"@otplib/plugin-thirty-two": "^12.0.1"
|
"@otplib/plugin-thirty-two": "^12.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@readme/data-urls": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@readme/data-urls/-/data-urls-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-b0L7VWqbLZqOSSAFUrxS5ZwUfec35WDsAwwCH481vYnhk0dWO3nvmNVNCbP8CY4cXqwL1W4uCAnhDz+CUmXM3g=="
|
||||||
|
},
|
||||||
"@selderee/plugin-htmlparser2": {
|
"@selderee/plugin-htmlparser2": {
|
||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
|
||||||
@@ -3716,17 +3730,6 @@
|
|||||||
"rrweb-cssom": "^0.6.0"
|
"rrweb-cssom": "^0.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"data-urls": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"abab": "^2.0.6",
|
|
||||||
"whatwg-mimetype": "^3.0.0",
|
|
||||||
"whatwg-url": "^12.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dayjs": {
|
"dayjs": {
|
||||||
"version": "1.11.9",
|
"version": "1.11.9",
|
||||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
|
||||||
@@ -4170,11 +4173,23 @@
|
|||||||
"xml-name-validator": "^4.0.0"
|
"xml-name-validator": "^4.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"data-urls": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"abab": "^2.0.6",
|
||||||
|
"whatwg-mimetype": "^3.0.0",
|
||||||
|
"whatwg-url": "^12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ws": {
|
"ws": {
|
||||||
"version": "8.13.0",
|
"version": "8.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||||
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"requires": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -4521,9 +4536,9 @@
|
|||||||
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
|
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
|
||||||
},
|
},
|
||||||
"punycode": {
|
"punycode": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="
|
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="
|
||||||
},
|
},
|
||||||
"qclone": {
|
"qclone": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@@ -4959,7 +4974,8 @@
|
|||||||
"ws": {
|
"ws": {
|
||||||
"version": "7.5.9",
|
"version": "7.5.9",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="
|
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||||
|
"requires": {}
|
||||||
},
|
},
|
||||||
"xml-name-validator": {
|
"xml-name-validator": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"@microsoft/signalr": "^7.0.10",
|
"@microsoft/signalr": "^7.0.10",
|
||||||
"@microsoft/signalr-protocol-msgpack": "^7.0.10",
|
"@microsoft/signalr-protocol-msgpack": "^7.0.10",
|
||||||
"@notesnook/logger": "file:../logger",
|
"@notesnook/logger": "file:../logger",
|
||||||
|
"@readme/data-urls": "^3.0.0",
|
||||||
"@streetwriters/showdown": "^3.0.2-alpha",
|
"@streetwriters/showdown": "^3.0.2-alpha",
|
||||||
"async-mutex": "^0.3.2",
|
"async-mutex": "^0.3.2",
|
||||||
"dayjs": "1.11.9",
|
"dayjs": "1.11.9",
|
||||||
|
|||||||
@@ -17,19 +17,30 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const REGEX = /^data:(image\/.+);base64,(.+)/;
|
import { parse, validate } from "@readme/data-urls";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} dataurl
|
||||||
|
* @returns {{mime?: string; data?: string}}
|
||||||
|
*/
|
||||||
function toObject(dataurl) {
|
function toObject(dataurl) {
|
||||||
const regexResult = REGEX.exec(dataurl);
|
const result = parse(dataurl);
|
||||||
if (!regexResult || regexResult.length < 3) return {};
|
if (!result) return {};
|
||||||
const [, mime, data] = regexResult;
|
return {
|
||||||
return { mime, data };
|
mime: result.contentType,
|
||||||
|
data: result.data
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function fromObject({ type, data }) {
|
function fromObject({ type, data }) {
|
||||||
if (REGEX.test(data)) return data;
|
if (validate(data)) return data;
|
||||||
return `data:${type};base64,${data}`;
|
return `data:${type};base64,${data}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataurl = { toObject, fromObject };
|
function isValid(url) {
|
||||||
|
return validate(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataurl = { toObject, fromObject, isValid };
|
||||||
export default dataurl;
|
export default dataurl;
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ import { Resizer } from "../../components/resizer";
|
|||||||
import {
|
import {
|
||||||
corsify,
|
corsify,
|
||||||
downloadImage,
|
downloadImage,
|
||||||
isDataUrl,
|
|
||||||
toBlobURL,
|
toBlobURL,
|
||||||
toDataURL
|
toDataURL
|
||||||
} from "../../utils/downloader";
|
} from "../../utils/downloader";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { useObserver } from "../../hooks/use-observer";
|
import { useObserver } from "../../hooks/use-observer";
|
||||||
import { Attachment, ImageAlignmentOptions } from "../attachment";
|
import { Attachment, ImageAlignmentOptions } from "../attachment";
|
||||||
|
import DataURL from "@notesnook/core/dist/utils/dataurl";
|
||||||
|
|
||||||
export const AnimatedImage = motion(Image);
|
export const AnimatedImage = motion(Image);
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ export function ImageComponent(
|
|||||||
const { src, alt, title, textDirection, hash, aspectRatio, mime } =
|
const { src, alt, title, textDirection, hash, aspectRatio, mime } =
|
||||||
node.attrs;
|
node.attrs;
|
||||||
const [bloburl, setBloburl] = useState<string | undefined>(
|
const [bloburl, setBloburl] = useState<string | undefined>(
|
||||||
toBlobURL("", hash)
|
toBlobURL("", "image", mime, hash)
|
||||||
);
|
);
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
@@ -82,11 +82,10 @@ export function ImageComponent(
|
|||||||
.catch(() => null);
|
.catch(() => null);
|
||||||
if (typeof data !== "string" || !data) return; // TODO: show error
|
if (typeof data !== "string" || !data) return; // TODO: show error
|
||||||
|
|
||||||
setBloburl(toBlobURL(data, hash));
|
setBloburl(toBlobURL(data, "image", node.attrs.mime, hash));
|
||||||
})();
|
})();
|
||||||
}, [inView]);
|
}, [inView]);
|
||||||
|
|
||||||
console.log({ width, height, aspectRatio });
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
@@ -263,7 +262,7 @@ export function ImageComponent(
|
|||||||
const naturalAspectRatio = orignalWidth / orignalHeight;
|
const naturalAspectRatio = orignalWidth / orignalHeight;
|
||||||
const fixedDimensions = fixAspectRatio(width, naturalAspectRatio);
|
const fixedDimensions = fixAspectRatio(width, naturalAspectRatio);
|
||||||
|
|
||||||
if (src && !isDataUrl(src) && canParse(src)) {
|
if (src && !DataURL.isValid(src) && canParse(src)) {
|
||||||
const image = await downloadImage(src, downloadOptions);
|
const image = await downloadImage(src, downloadOptions);
|
||||||
if (!image) return;
|
if (!image) return;
|
||||||
const { url, size, blob, mimeType } = image;
|
const { url, size, blob, mimeType } = image;
|
||||||
@@ -292,7 +291,6 @@ export function ImageComponent(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else if (height !== fixedDimensions.height) {
|
} else if (height !== fixedDimensions.height) {
|
||||||
console.log("RESETTING HEIGHT");
|
|
||||||
await editor.threadsafe((editor) =>
|
await editor.threadsafe((editor) =>
|
||||||
editor.commands.updateAttachment(fixedDimensions, {
|
editor.commands.updateAttachment(fixedDimensions, {
|
||||||
query: makeImageQuery(src, hash)
|
query: makeImageQuery(src, hash)
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ const UTITypes: Record<string, string> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function corsify(url?: string, host?: string) {
|
export function corsify(url?: string, host?: string) {
|
||||||
if (host && url && !url.startsWith("blob:") && !isDataUrl(url))
|
if (host && url && !url.startsWith("blob:") && !DataURL.isValid(url))
|
||||||
return `${host}/${url}`;
|
return `${host}/${url}`;
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
@@ -115,17 +115,28 @@ export function toDataURL(blob: Blob): Promise<string> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isDataUrl(url?: string): boolean {
|
|
||||||
return url?.startsWith("data:") || false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const OBJECT_URL_CACHE: Record<string, string | undefined> = {};
|
const OBJECT_URL_CACHE: Record<string, string | undefined> = {};
|
||||||
export function toBlobURL(dataurl: string, id?: string) {
|
export function toBlobURL(
|
||||||
|
dataurl: string,
|
||||||
|
type: "image" | "other" = "other",
|
||||||
|
mimeType?: string,
|
||||||
|
id?: string
|
||||||
|
) {
|
||||||
if (id && OBJECT_URL_CACHE[id]) return OBJECT_URL_CACHE[id];
|
if (id && OBJECT_URL_CACHE[id]) return OBJECT_URL_CACHE[id];
|
||||||
if (!isDataUrl(dataurl)) return;
|
if (!DataURL.isValid(dataurl)) return;
|
||||||
|
|
||||||
|
const dataurlObject = DataURL.toObject(dataurl);
|
||||||
|
let mime = dataurlObject.mime || "";
|
||||||
|
const data = dataurlObject.data;
|
||||||
|
|
||||||
|
if (!data) return;
|
||||||
|
|
||||||
|
// sometimes the provided mime type in the dataurl can be wrong so we
|
||||||
|
// fallback and make sure the browser loads the image properly.
|
||||||
|
if (type === "image" && !mime.startsWith("image/")) {
|
||||||
|
mime = mimeType && mimeType.startsWith("image/") ? mimeType : "image/*";
|
||||||
|
}
|
||||||
|
|
||||||
const { data, mime } = DataURL.toObject(dataurl); //.split(",");
|
|
||||||
if (!data || !mime) return;
|
|
||||||
const objectURL = URL.createObjectURL(
|
const objectURL = URL.createObjectURL(
|
||||||
new Blob([Buffer.from(data, "base64")], { type: mime })
|
new Blob([Buffer.from(data, "base64")], { type: mime })
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user