UNPKG

js-draw

Version:

Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript.

127 lines (126 loc) 5.02 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const TextComponent_1 = __importDefault(require("../components/TextComponent")); const SVGLoader_1 = __importDefault(require("../SVGLoader/SVGLoader")); const math_1 = require("@js-draw/math"); const BaseTool_1 = __importDefault(require("./BaseTool")); const TextTool_1 = __importDefault(require("./TextTool")); const ImageComponent_1 = __importDefault(require("../components/ImageComponent")); /** * A tool that handles paste events (e.g. as triggered by ctrl+V). * * @example * While `ToolController` has a `PasteHandler` in its default list of tools, * if a non-default set is being used, `PasteHandler` can be added as follows: * ```ts * const toolController = editor.toolController; * toolController.addTool(new PasteHandler(editor)); * ``` */ class PasteHandler extends BaseTool_1.default { constructor(editor) { super(editor.notifier, editor.localization.pasteHandler); this.editor = editor; } // @internal onPaste(event, onComplete) { const mime = event.mime.toLowerCase(); const svgData = (() => { if (mime === 'image/svg+xml') { return event.data; } // In some environments, it isn't possible to write non-text data to the // clipboard. To support these cases, auto-detect text/plain SVG data. if (mime === 'text/plain') { const trimmedData = event.data.trim(); if (trimmedData.startsWith('<svg') && trimmedData.endsWith('</svg>')) { return trimmedData; } } if (mime !== 'text/html') { return false; } // text/html is sometimes handlable SVG data. Use a hueristic // to determine if this is the case: // We use [^] and not . so that newlines are included. const match = event.data.match(/^[^]{0,200}<svg.*/i); // [^]{0,200} <- Allow for metadata near start if (!match) { return false; } // Extract the SVG element from the pasted data let svgEnd = event.data.toLowerCase().lastIndexOf('</svg>'); if (svgEnd === -1) svgEnd = event.data.length; return event.data.substring(event.data.search(/<svg/i), svgEnd); })(); if (svgData) { void this.doSVGPaste(svgData).then(onComplete); return true; } else if (mime === 'text/plain') { void this.doTextPaste(event.data).then(onComplete); return true; } else if (mime === 'image/png' || mime === 'image/jpeg') { void this.doImagePaste(event.data).then(onComplete); return true; } return false; } async addComponentsFromPaste(components) { await this.editor.addAndCenterComponents(components, true, this.editor.localization.pasted(components.length)); } async doSVGPaste(data) { this.editor.showLoadingWarning(0); try { const loader = SVGLoader_1.default.fromString(data, { sanitize: true, plugins: this.editor.getCurrentSettings().svg?.loaderPlugins ?? [], }); const components = []; await loader.start((component) => { components.push(component); }, (_countProcessed, _totalToProcess) => null); await this.addComponentsFromPaste(components); } finally { this.editor.hideLoadingWarning(); } } async doTextPaste(text) { const textTools = this.editor.toolController.getMatchingTools(TextTool_1.default); textTools.sort((a, b) => { if (!a.isEnabled() && b.isEnabled()) { return -1; } if (!b.isEnabled() && a.isEnabled()) { return 1; } return 0; }); const defaultTextStyle = { size: 12, fontFamily: 'sans', renderingStyle: { fill: math_1.Color4.red }, }; const pastedTextStyle = textTools[0]?.getTextStyle() ?? defaultTextStyle; // Don't paste text that would be invisible. if (text.trim() === '') { return; } const lines = text.split('\n'); await this.addComponentsFromPaste([ TextComponent_1.default.fromLines(lines, math_1.Mat33.identity, pastedTextStyle), ]); } async doImagePaste(dataURL) { const image = new Image(); image.src = dataURL; const component = await ImageComponent_1.default.fromImage(image, math_1.Mat33.identity); await this.addComponentsFromPaste([component]); } } exports.default = PasteHandler;