├── LICENSE ├── app └── src │ ├── engine │ ├── license-store.js │ └── diagram-export.js │ └── dialogs │ └── license-activation-dialog.js └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 RodyUzuriaga 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/src/engine/license-store.js: -------------------------------------------------------------------------------- 1 | const { ipcRenderer } = require("electron"); 2 | const { EventEmitter } = require("events"); 3 | const LicenseActivationDialog = require("../dialogs/license-activation-dialog"); 4 | 5 | class LicenseStore extends EventEmitter { 6 | constructor() { 7 | super(); 8 | // Always return a PRO license activated status 9 | this.licenseStatus = { 10 | activated: true, 11 | name: "Licensed User", 12 | product: "staruml-v7", 13 | edition: "PRO", 14 | productDisplayName: "StarUML v7.0.0", 15 | deviceId: "unlimited-device", 16 | licenseKey: "unlimited-license-key", 17 | activationCode: "unlimited-activation-code", 18 | trial: false, 19 | trialDaysLeft: 0, 20 | }; 21 | } 22 | 23 | async fetch() { 24 | // Always return the PRO license status 25 | this.emit("statusChanged", this.licenseStatus); 26 | } 27 | 28 | async getDeviceId() { 29 | try { 30 | // Return a fake device ID 31 | return "unlimited-device-id"; 32 | } catch (err) { 33 | console.error(err); 34 | return "unlimited-device-id"; 35 | } 36 | } 37 | 38 | async activate(licenseKey) { 39 | try { 40 | // Always return success for any license key 41 | app.toast.info("License activated successfully!"); 42 | } catch (err) { 43 | console.error(err); 44 | app.toast.info("License activated successfully!"); 45 | } 46 | await this.fetch(); 47 | } 48 | 49 | async deactivate() { 50 | try { 51 | // Do nothing, keep the license active 52 | app.toast.info("License remains active"); 53 | } catch (err) { 54 | console.error(err); 55 | app.toast.info("License remains active"); 56 | } 57 | await this.fetch(); 58 | } 59 | 60 | async validate() { 61 | // Always return successful validation 62 | return { success: true, message: "License valid" }; 63 | } 64 | 65 | getLicenseStatus() { 66 | // Always return PRO license status 67 | return this.licenseStatus; 68 | } 69 | 70 | async checkTrialMode() { 71 | // Never show trial dialog since we're always licensed 72 | // LicenseActivationDialog.showDialog(); // Commented out 73 | } 74 | 75 | async htmlReady() { 76 | try { 77 | await this.fetch(); 78 | const result = await this.validate(); 79 | if (!result.success) { 80 | // This should never happen with our modifications 81 | app.toast.info("License validated successfully!"); 82 | } 83 | // Skip trial check since we're always licensed 84 | await this.fetch(); 85 | } catch (err) { 86 | console.error(err); 87 | console.log("License validation successful (fallback)"); 88 | } 89 | } 90 | } 91 | 92 | module.exports = LicenseStore; -------------------------------------------------------------------------------- /app/src/dialogs/license-activation-dialog.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2014 Minkyu Lee. All rights reserved. 3 | * 4 | * NOTICE: All information contained herein is, and remains the 5 | * property of Minkyu Lee. The intellectual and technical concepts 6 | * contained herein are proprietary to Minkyu Lee and may be covered 7 | * by Republic of Korea and Foreign Patents, patents in process, 8 | * and are protected by trade secret or copyright law. 9 | * Dissemination of this information or reproduction of this material 10 | * is strictly forbidden unless prior written permission is obtained 11 | * from Minkyu Lee (niklaus.lee@gmail.com). 12 | * 13 | */ 14 | 15 | const { shell, clipboard } = require("electron"); 16 | const fs = require("fs"); 17 | const path = require("path"); 18 | const Mustache = require("mustache"); 19 | const Strings = require("../strings"); 20 | 21 | const licenseActivationDialogTemplate = fs.readFileSync( 22 | path.join( 23 | __dirname, 24 | "../static/html-contents/license-activation-dialog.html", 25 | ), 26 | "utf8", 27 | ); 28 | 29 | async function updateDialog($dlg) { 30 | // Always use our fake PRO license status 31 | const licenseStatus = { 32 | trial: false, 33 | trialDaysLeft: 0, 34 | activated: true, 35 | productDisplayName: "StarUML v7.0.0 PRO", 36 | name: "Licensed User", 37 | deviceId: "unlimited-device", 38 | }; 39 | 40 | const $sectionTrialNotExpired = $dlg.find(".trial-not-expired"); 41 | const $sectionTrialExpired = $dlg.find(".trial-expired"); 42 | const $sectionLicenseActivated = $dlg.find(".license-activated"); 43 | const $sectionLicenseNotActivated = $dlg.find(".license-not-activated"); 44 | const $trialDaysLeft = $dlg.find(".trial-days-left"); 45 | const $activeStatus = $dlg.find(".active-status"); 46 | const $productDisplayName = $dlg.find(".product-display-name"); 47 | const $licenseHolderName = $dlg.find(".license-holder-name"); 48 | const $deviceId = $dlg.find(".device-id"); 49 | 50 | // Hide all trial sections 51 | $sectionTrialNotExpired.hide(); 52 | $sectionTrialExpired.hide(); 53 | $sectionLicenseNotActivated.hide(); 54 | 55 | // Always show license activated 56 | $sectionLicenseActivated.show(); 57 | 58 | $trialDaysLeft.text("0"); 59 | $activeStatus.text("Activated (PRO License)"); 60 | $productDisplayName.text(licenseStatus.productDisplayName); 61 | $licenseHolderName.text(licenseStatus.name); 62 | $deviceId.text("unlimited"); 63 | } 64 | 65 | /** 66 | * Show License Activation Dialog 67 | * @private 68 | * @return {Dialog} 69 | */ 70 | async function showDialog() { 71 | // Don't fetch from store, use our static values 72 | const context = { 73 | Strings: Strings, 74 | metadata: global.app.metadata, 75 | }; 76 | const dialog = app.dialogs.showModalDialogUsingTemplate( 77 | Mustache.render(licenseActivationDialogTemplate, context), 78 | ); 79 | 80 | const $dlg = dialog.getElement(); 81 | const $buyButton = $dlg.find(".buy-button"); 82 | const $licenseKey = $dlg.find(".license-key"); 83 | const $activateButton = $dlg.find(".activate-button"); 84 | const $deactivateButton = $dlg.find(".deactivate-button"); 85 | const $copyDeviceIdButton = $dlg.find(".copy-device-id-button"); 86 | const $licenseManagerButton = $dlg.find(".license-manager-button"); 87 | await updateDialog($dlg); 88 | 89 | $activateButton.click(async function () { 90 | // Always show success 91 | app.toast.info("License already activated!"); 92 | setTimeout(async () => { 93 | await updateDialog($dlg); 94 | }, 0); 95 | }); 96 | 97 | $deactivateButton.click(async function () { 98 | // Prevent deactivation 99 | app.toast.info("License remains active"); 100 | setTimeout(async () => { 101 | await updateDialog($dlg); 102 | }, 0); 103 | }); 104 | 105 | $buyButton.click(function () { 106 | // Optional: still allow opening purchase page 107 | shell.openExternal(app.config.purchase_url); 108 | }); 109 | 110 | $copyDeviceIdButton.click(async function () { 111 | clipboard.writeText("unlimited-device-id"); 112 | app.toast.info("Device ID copied to clipboard."); 113 | }); 114 | 115 | $licenseManagerButton.click(function () { 116 | shell.openExternal(app.config.license_manager_url); 117 | }); 118 | 119 | dialog.then(function ({ buttonId }) { 120 | // Never set readonly mode - always allow full access 121 | app.repository._readonly = false; 122 | app.diagrams.diagramEditor._readonly = false; 123 | app.propertyEditorView._readonly = false; 124 | }); 125 | 126 | return dialog; 127 | } 128 | 129 | exports.showDialog = showDialog; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StarUML v7.0.0 Full License & Exporting Diagrams in High Resolution 2 | 3 | This guide will walk you through how to license StarUML v7.0.0 and export diagrams without watermarks in high resolution. Follow each step carefully to ensure success. 4 | 5 | MAY YOU ENJOY IT 6 | 7 | --- 8 | 9 | ## 🚀 What's New in v7.0.0 10 | 11 | StarUML v7.0.0 introduced a new license system with enhanced security measures, but we've got you covered! This updated method ensures you get the full PRO features without any limitations. 12 | 13 | --- 14 | 15 | ## 1. Install StarUML v7.0.0 16 | Download the latest version of StarUML v7.0.0 from the [official website](https://staruml.io/download). 17 | 18 | --- 19 | 20 | ## 2. Install `asar` 21 | Install `asar`, a utility to manage `.asar` files. Open your terminal as an administrator and run the following command: 22 | 23 | ```bash 24 | npm i asar -g 25 | ``` 26 | > [!IMPORTANT] 27 | > Make sure to have the **LTS** version of Node.js installed to ensure compatibility and avoid errors when running `npm` commands. You can download the LTS version from [nodejs.org](https://nodejs.org/). 28 | 29 | This will install `asar` globally. 30 | 31 | --- 32 | 33 | ## 3. Extract `app.asar` 34 | To access the files needed to modify the license and export settings, extract the `app.asar` file. 35 | 36 | Navigate to the StarUML directory. By default, it's located at: 37 | 38 | - **Windows**: `C:/Program Files/StarUML/resources` 39 | - **MacOS**: `/Applications/StarUML.app/Contents/Resources` 40 | - **Linux**: `/opt/staruml/resources` 41 | 42 | You can use the `cd` command to navigate to your specific directory. For example: 43 | 44 | ```bash 45 | cd "C:/Program Files/StarUML/resources" 46 | ``` 47 | 48 | Run the following command in your terminal as an Administrator (Git Bash, PowerShell, or CMD): 49 | 50 | ```bash 51 | asar e app.asar app 52 | ``` 53 | 54 | This will extract the `app.asar` file into a folder called `app`. 55 | 56 | --- 57 | 58 | ## 4. Copy Modified Files 59 | 60 | Instead of manually editing files, simply copy the pre-modified files from this repository to your extracted StarUML folder. 61 | 62 | ### Copy the modified files: 63 | 64 | 1. Navigate to the `app` folder you just extracted 65 | 2. Copy the `license-store.js` file from this repository to: 66 | ``` 67 | app/src/engine/license-store.js 68 | ``` 69 | 70 | 3. Copy the `diagram-export.js` file from this repository to: 71 | ``` 72 | app/src/engine/diagram-export.js 73 | ``` 74 | 75 | 4. Copy the `license-activation-dialog.js` file from this repository to: 76 | ``` 77 | app/src/dialogs/license-activation-dialog.js 78 | ``` 79 | 80 | ### File locations: 81 | - **License file**: `app/src/engine/license-store.js` 82 | - **Export file**: `app/src/engine/diagram-export.js` 83 | - **Dialog file**: `app/src/dialogs/license-activation-dialog.js` 84 | 85 | > [!TIP] 86 | > Simply replace the existing files with the ones provided in this repository. The modified files ensure you get full PRO features and high-quality exports without watermarks. 87 | 88 | --- 89 | 90 | ## 5. What These Files Do 91 | 92 | ### 🔑 `license-store.js` - Full License Activation 93 | - **Always returns PRO license status**: The app will always think you have a valid PRO license 94 | - **Removes trial limitations**: No more 30-day trial restrictions 95 | - **Unlimited features**: Access to all PRO diagram types and features 96 | - **No license validation**: Bypasses all license checking mechanisms 97 | 98 | ### 🎨 `diagram-export.js` - High-Quality Exports 99 | - **No watermarks**: Completely removes "UNREGISTERED" and "PRO ONLY" watermarks 100 | - **Enhanced image quality**: Uses the exact same high-quality configuration from v6.2.2 101 | - **Full workspace capture**: Captures the complete diagram workspace without cropping 102 | - **Maximum quality**: All exports use the highest quality settings (quality: 1.0) 103 | - **Support for all formats**: PNG, JPEG, SVG, and PDF exports without limitations 104 | 105 | ### 💬 `license-activation-dialog.js` - Dialog Modifications 106 | - **Always shows activated**: License dialog always displays PRO status 107 | - **Prevents deactivation**: Blocks any attempts to deactivate the license 108 | - **No readonly mode**: Ensures full editing capabilities are always available 109 | - **Seamless experience**: User interface reflects full PRO license status 110 | 111 | --- 112 | 113 | ## 6. Repack `app.asar` 114 | 115 | Once you have copied the modified files, you need to repack the `app.asar` file. Navigate back to the `resources` directory and run the following command: 116 | 117 | ```bash 118 | asar pack app app.asar 119 | ``` 120 | 121 | This will repack your modified `app` folder back into a `.asar` file. 122 | 123 | --- 124 | 125 | ## 7. Clean Up 126 | 127 | After repacking the `app.asar`, you can safely remove the extracted `app` folder to clean up your directory. 128 | 129 | ### Remove the app folder: 130 | 131 | - **For Windows:** 132 | ```bash 133 | rmdir /s /q app 134 | ``` 135 | 136 | - **For Linux or Mac:** 137 | ```bash 138 | rm -rf app 139 | ``` 140 | 141 | --- 142 | 143 | ## 8. Launch StarUML 144 | 145 | Now that everything is set up, launch StarUML by running the `StarUML.exe` file from your installation directory or through the desktop shortcut. 146 | 147 | --- 148 | 149 | ## ✨ Features You'll Get 150 | 151 | With these modifications, you'll have access to: 152 | 153 | - ✅ **Full PRO License**: All features unlocked 154 | - ✅ **All Diagram Types**: Including SysML, BPMN, Wireframes, AWS, GCP diagrams 155 | - ✅ **High-Resolution Exports**: Crystal clear PNG, JPEG exports 156 | - ✅ **Watermark-Free**: Clean exports without any watermarks 157 | - ✅ **PDF Export**: Professional PDF exports without limitations 158 | - ✅ **SVG Export**: Vector graphics with enhanced quality 159 | - ✅ **No Trial Restrictions**: Unlimited usage time 160 | 161 | --- 162 | 163 | ## 🎯 Enjoy! 164 | 165 | Congratulations! You now have StarUML v7.0.0 fully licensed and can export diagrams in high resolution without watermarks. 166 | 167 | > [!NOTE] 168 | > This guide applies specifically to StarUML version 7.0.0. The license system was updated in this version, which is why we use `license-store.js` instead of the previous `license-manager.js`. 169 | 170 | > [!WARNING] 171 | > This modification is for educational and personal use only. Please consider supporting the developers by purchasing a legitimate license if you use StarUML professionally. 172 | 173 | --- 174 | 175 | ## 📋 File Structure 176 | 177 | Your repository should look like this: 178 | ``` 179 | Get-full-version-of-StarUML-7.0.0-Pro-Remove-Watermark/ 180 | ├── README.md 181 | └── app/ 182 | └── src/ 183 | ├── engine/ 184 | │ ├── license-store.js 185 | │ └── diagram-export.js 186 | └── dialogs/ 187 | └── license-activation-dialog.js 188 | ``` 189 | 190 | --- 191 | 192 | ## 🔧 Troubleshooting 193 | 194 | If you encounter any issues: 195 | 196 | 1. **Make sure you're running terminal as Administrator** 197 | 2. **Verify Node.js and asar are properly installed** 198 | 3. **Ensure you're in the correct directory when running commands** 199 | 4. **Check that the file paths match exactly** 200 | 5. **Restart StarUML completely after making changes** 201 | 202 | --- 203 | 204 | Made with ❤️ for the StarUML community -------------------------------------------------------------------------------- /app/src/engine/diagram-export.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 MKLab. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | /* global C2S */ 25 | 26 | const fs = require("fs-extra"); 27 | const filenamify = require("filenamify"); 28 | const PDFDocument = require("pdfkit"); 29 | const { Point, ZoomFactor, Canvas } = require("../core/graphics"); 30 | const { PDFCanvas } = require("./pdf-graphics"); 31 | const { Context } = require("svgcanvas"); 32 | 33 | const BOUNDING_BOX_EXPAND = 10; 34 | 35 | const PDF_MARGIN = 30; 36 | const PDF_DEFAULT_ZOOM = 1; // Default Zoom Level 37 | 38 | const PRO_DIAGRAM_TYPES = [ 39 | "SysMLRequirementDiagram", 40 | "SysMLBlockDefinitionDiagram", 41 | "SysMLInternalBlockDiagram", 42 | "SysMLParametricDiagram", 43 | "BPMNDiagram", 44 | "WFWireframeDiagram", 45 | "AWSDiagram", 46 | "GCPDiagram", 47 | ]; 48 | 49 | function isProDiagram(diagramType) { 50 | // Always return false - treat all diagrams as free/unlimited 51 | return false; 52 | } 53 | 54 | /** 55 | * @private 56 | * SVGCanavas for SVG Export 57 | */ 58 | class SVGCanvas extends Canvas { 59 | /** 60 | * To embed svg image in the exported svg file, we need to convert the svg image to base64 61 | */ 62 | drawImage(image, x, y, w, h) { 63 | this.transform(); 64 | if ( 65 | typeof image.src === "string" && 66 | image.src.toLowerCase().startsWith("file://") 67 | ) { 68 | if (image.src.toLowerCase().endsWith(".svg")) { 69 | const filePath = image.src.substring(7); 70 | if (fs.existsSync(filePath)) { 71 | const svgString = fs.readFileSync(filePath, "utf8"); 72 | const base64Svg = btoa(unescape(encodeURIComponent(svgString))); 73 | const data = `data:image/svg+xml;base64,${base64Svg}`; 74 | const img = new Image(); 75 | img.src = data; 76 | img.width = image.width; 77 | img.height = image.height; 78 | this.context.drawImage(img, x, y, w, h); 79 | } 80 | } else if (image.src.toLowerCase().endsWith(".png")) { 81 | const filePath = image.src.substring(7); 82 | if (fs.existsSync(filePath)) { 83 | const pngBuffer = fs.readFileSync(filePath); 84 | const base64String = pngBuffer.toString("base64"); 85 | const data = `data:image/png;base64,${base64String}`; 86 | const img = new Image(); 87 | img.src = data; 88 | img.width = image.width; 89 | img.height = image.height; 90 | this.context.drawImage(img, x, y, w, h); 91 | } 92 | } 93 | } else { 94 | this.context.drawImage(image, x, y, w, h); 95 | } 96 | this.restoreTransform(); 97 | } 98 | } 99 | 100 | /** 101 | * @private 102 | * Get Base64-encoded image data of diagram 103 | * @param {Editor} editor 104 | * @param {string} type (e.g. 'image/png') 105 | * @return {string} 106 | */ 107 | function getImageData(diagram, type) { 108 | // Crear un nuevo canvas para generar la imagen 109 | var canvasElement = document.createElement("canvas"); 110 | var canvas = new Canvas(canvasElement.getContext("2d")); 111 | var boundingBox = diagram.getBoundingBox(canvas); 112 | 113 | // Initialize new canvas 114 | // Expandir el boundingBox para asegurar que se incluya todo el diagrama 115 | boundingBox.expand(BOUNDING_BOX_EXPAND); 116 | // Ajustar el origen del canvas para no recortar el diagrama 117 | canvas.origin = new Point(-boundingBox.x1, -boundingBox.y1); 118 | canvas.zoomFactor = new ZoomFactor(1, 1); 119 | canvas.context.imageSmoothingEnabled = true; 120 | canvas.context.imageSmoothingQuality = 'high'; 121 | canvas.context.textRenderingOptimization = 'optimizeQuality'; 122 | // Aquí calculamos el tamaño real del canvas antes de aplicar la relación de píxeles 123 | canvasElement.width = boundingBox.getWidth(); // Anchura real 124 | canvasElement.height = boundingBox.getHeight(); // Altura real 125 | 126 | // Configuración para pantallas de alta DPI (Retina) - configuración exacta de v6.2.2 127 | if (window.devicePixelRatio) { 128 | var ratio = window.devicePixelRatio * 4; // Ajustar el ratio para alta calidad 129 | canvasElement.width *= ratio; // Aumentar la anchura según el ratio 130 | canvasElement.height *= ratio; // Aumentar la altura según el ratio 131 | canvas.context.scale(ratio, ratio); // Escalar el contexto del canvas 132 | } 133 | 134 | // Dibujar un fondo blanco solo para JPEG (para evitar el fondo transparente) 135 | if (type === "image/jpeg") { 136 | canvas.context.fillStyle = "#ffffff"; 137 | canvas.context.fillRect(0, 0, canvasElement.width, canvasElement.height); 138 | } 139 | 140 | // REMOVED: All watermark drawing code - no watermarks will be applied 141 | // const licenseStatus = app.licenseStore.getLicenseStatus(); 142 | // Draw watermark if application is not registered 143 | // if (licenseStatus.trial) { 144 | // diagram.drawWatermark( 145 | // canvas, 146 | // canvasElement.width, 147 | // canvasElement.height, 148 | // 70, 149 | // 12, 150 | // "UNREGISTERED", 151 | // ); 152 | // } else if (licenseStatus.edition !== "PRO") { 153 | // const dgmType = diagram.constructor.name; 154 | // if (isProDiagram(dgmType)) { 155 | // diagram.drawWatermark( 156 | // canvas, 157 | // canvasElement.width, 158 | // canvasElement.height, 159 | // 45, 160 | // 12, 161 | // "PRO ONLY", 162 | // ); 163 | // } 164 | // } 165 | 166 | // Dibujar el diagrama en el nuevo canvas 167 | diagram.arrangeDiagram(canvas); 168 | diagram.drawDiagram(canvas); 169 | 170 | // Devolver los datos del canvas en base64 con máxima calidad 171 | var data = canvasElement.toDataURL(type, 1.0).replace(/^data:image\/(png|jpeg);base64,/, ""); 172 | return data; 173 | } 174 | 175 | /** 176 | * @private 177 | * Get SVG image data of editor.diagram 178 | * @param {Diagram} diagram 179 | * @return {string} 180 | */ 181 | function getSVGImageData(diagram) { 182 | const boundingBox = diagram.getBoundingBox(canvas); 183 | boundingBox.expand(BOUNDING_BOX_EXPAND); 184 | const w = boundingBox.getWidth(); 185 | const h = boundingBox.getHeight(); 186 | 187 | // Make a new SVG canvas for making SVG image data 188 | var ctx = new Context(w, h); 189 | var canvas = new SVGCanvas(ctx); 190 | 191 | // Initialize new SVG Canvas - configuración exacta de v6.2.2 192 | canvas.origin = new Point(-boundingBox.x1, -boundingBox.y1); 193 | canvas.zoomFactor = new ZoomFactor(2, 2); // Aplicamos un zoom adicional para mayor calidad 194 | 195 | // REMOVED: All watermark drawing code - no watermarks will be applied 196 | // const licenseStatus = app.licenseStore.getLicenseStatus(); 197 | // Draw watermark if application is not registered 198 | // if (licenseStatus.trial) { 199 | // diagram.drawWatermark( 200 | // canvas, 201 | // boundingBox.getWidth(), 202 | // boundingBox.getHeight(), 203 | // 70, 204 | // 12, 205 | // "UNREGISTERED", 206 | // ); 207 | // } else if (licenseStatus.edition !== "PRO") { 208 | // const dgmType = diagram.constructor.name; 209 | // if (isProDiagram(dgmType)) { 210 | // diagram.drawWatermark( 211 | // canvas, 212 | // boundingBox.getWidth(), 213 | // boundingBox.getHeight(), 214 | // 45, 215 | // 12, 216 | // "PRO ONLY", 217 | // ); 218 | // } 219 | // } 220 | 221 | // Draw diagram to the new SVG Canvas 222 | diagram.arrangeDiagram(canvas); 223 | diagram.drawDiagram(canvas); 224 | 225 | // Return the SVG data 226 | var data = ctx.getSerializedSvg(true); 227 | return data; 228 | } 229 | 230 | /** 231 | * @private 232 | * Export Diagram as PNG 233 | * 234 | * @param {Diagram} diagram 235 | * @param {string} fullPath 236 | */ 237 | function exportToPNG(diagram, fullPath) { 238 | diagram.deselectAll(); 239 | var data = getImageData(diagram, "image/png"); 240 | var buffer = Buffer.from(data, "base64"); 241 | fs.writeFileSync(fullPath, buffer); 242 | } 243 | 244 | /** 245 | * @private 246 | * Export Diagram as JPEG 247 | * 248 | * @param {Diagram} diagram 249 | * @param {string} fullPath 250 | */ 251 | function exportToJPEG(diagram, fullPath) { 252 | diagram.deselectAll(); 253 | var data = getImageData(diagram, "image/jpeg"); 254 | var buffer = Buffer.from(data, "base64"); 255 | fs.writeFileSync(fullPath, buffer); 256 | } 257 | 258 | /** 259 | * @private 260 | * Export Diagram as SVG 261 | * 262 | * @param {Diagram} diagram 263 | * @param {string} fullPath 264 | */ 265 | function exportToSVG(diagram, fullPath) { 266 | diagram.deselectAll(); 267 | var data = getSVGImageData(diagram); 268 | fs.writeFileSync(fullPath, data, "utf8"); 269 | } 270 | 271 | /** 272 | * @private 273 | * Export a list of diagrams 274 | * 275 | * @param {string} format One of `png`, `jpg`, `svg`. 276 | * @param {Array} diagrams 277 | * @param {string} basePath 278 | */ 279 | function exportAll(format, diagrams, basePath) { 280 | if (diagrams && diagrams.length > 0) { 281 | const path = basePath + "/" + format; 282 | fs.ensureDirSync(path); 283 | diagrams.forEach((diagram, idx) => { 284 | var fn = 285 | path + 286 | "/" + 287 | filenamify(diagram.getPathname()) + 288 | "_" + 289 | idx + 290 | "." + 291 | format; 292 | switch (format) { 293 | case "png": 294 | return exportToPNG(diagram, fn); 295 | case "jpg": 296 | return exportToJPEG(diagram, fn); 297 | case "svg": 298 | return exportToSVG(diagram, fn); 299 | } 300 | }); 301 | } 302 | } 303 | 304 | function drawWatermarkPDF(doc, xstep, ystep, text) { 305 | // REMOVED: Watermark function - now does nothing 306 | // doc.font("Helvetica"); 307 | // doc.fontSize(8); 308 | // doc.fillColor("#eeeeee"); 309 | // for (var i = 0, wx = doc.page.width; i < wx; i += xstep) { 310 | // for (var j = 0, wy = doc.page.height; j < wy; j += ystep) { 311 | // doc.text(text, i, j, { lineBreak: false }); 312 | // } 313 | // } 314 | } 315 | 316 | /** 317 | * @private 318 | * Export diagrams to a PDF file 319 | * @param{Array} diagrams 320 | * @param{string} fullPath 321 | * @param{Object} options 322 | */ 323 | function exportToPDF(diagrams, fullPath, options) { 324 | var doc = new PDFDocument(options); 325 | // eslint-disable-next-line guard-for-in 326 | for (let name in app.fontManager.files) { 327 | const path = app.fontManager.files[name]; 328 | doc.registerFont(name, path); 329 | } 330 | doc.pipe(fs.createWriteStream(fullPath)); 331 | var i, len; 332 | for (i = 0, len = diagrams.length; i < len; i++) { 333 | var canvas = new PDFCanvas(doc); 334 | if (i > 0) { 335 | doc.addPage(options); 336 | } 337 | var diagram = diagrams[i]; 338 | var box = diagram.getBoundingBox(canvas); 339 | var w = doc.page.width - PDF_MARGIN * 2; 340 | var h = doc.page.height - PDF_MARGIN * 2; 341 | var zoom = Math.min(w / box.x2, h / box.y2); 342 | canvas.baseOrigin.x = PDF_MARGIN; 343 | canvas.baseOrigin.y = PDF_MARGIN; 344 | canvas.baseScale = Math.min(zoom, PDF_DEFAULT_ZOOM); 345 | 346 | // REMOVED: All watermark drawing code for PDF - no watermarks will be applied 347 | // Draw watermark if application is not registered 348 | // const licenseStatus = app.licenseStore.getLicenseStatus(); 349 | // if (licenseStatus.trial) { 350 | // drawWatermarkPDF(doc, 70, 12, "UNREGISTERED"); 351 | // } else if (licenseStatus.edition !== "PRO") { 352 | // const dgmType = diagram.constructor.name; 353 | // if (isProDiagram(dgmType)) { 354 | // drawWatermarkPDF(doc, 45, 12, "PRO ONLY"); 355 | // } 356 | // } 357 | 358 | diagram.arrangeDiagram(canvas); 359 | diagram.drawDiagram(canvas, false); 360 | 361 | if (options.showName) { 362 | doc.fontSize(10); 363 | doc.font("Helvetica"); 364 | canvas.textOut(0, -10, diagram.getPathname()); 365 | } 366 | } 367 | doc.end(); 368 | } 369 | 370 | exports.getImageData = getImageData; 371 | exports.getSVGImageData = getSVGImageData; 372 | exports.exportToPNG = exportToPNG; 373 | exports.exportToJPEG = exportToJPEG; 374 | exports.exportToSVG = exportToSVG; 375 | exports.exportAll = exportAll; 376 | exports.exportToPDF = exportToPDF; --------------------------------------------------------------------------------