diff --git a/sdkjs-plugins/content/mathpix/3rd-Party.txt b/sdkjs-plugins/content/mathpix/3rd-Party.txt new file mode 100644 index 00000000..33955103 --- /dev/null +++ b/sdkjs-plugins/content/mathpix/3rd-Party.txt @@ -0,0 +1,14 @@ +This plugin uses code from the following 3rd party projects: + +1. MathJax (https://www.mathjax.org/) +License: Apache License 2.0 +https://github.com/mathjax/MathJax/blob/master/LICENSE + +2. Mathpix API (https://mathpix.com/) +Terms of Service: https://mathpix.com/terms +Privacy Policy: https://mathpix.com/privacy + +3. Mathpix Logo/Favicon (https://mathpix.com/favicon.ico) +Copyright (c) Mathpix, Inc. +Used with permission as part of the Mathpix API integration + diff --git a/sdkjs-plugins/content/mathpix/CHANGELOG.md b/sdkjs-plugins/content/mathpix/CHANGELOG.md new file mode 100644 index 00000000..92d93305 --- /dev/null +++ b/sdkjs-plugins/content/mathpix/CHANGELOG.md @@ -0,0 +1,7 @@ +# Change Log + +## 1.0.0 + +* Initial release. + + diff --git a/sdkjs-plugins/content/mathpix/README.md b/sdkjs-plugins/content/mathpix/README.md new file mode 100644 index 00000000..c93dfa00 --- /dev/null +++ b/sdkjs-plugins/content/mathpix/README.md @@ -0,0 +1,103 @@ +# Mathpix Plugin for ONLYOFFICE + +Convert mathematical formulas from images to editable text! This plugin allows you to easily extract mathematical formulas and text from images and insert them directly into your ONLYOFFICE documents. + +## 🌟 Key Features + +- **Multiple Input Methods**: + - Click to upload images + - Support for batch uploading multiple images + +- **Smart Recognition**: + - Automatic recognition of mathematical formulas and text + - Real-time preview of recognition results + - Support for manual editing of results + +- **Flexible Output Formats**: + - LaTeX (ideal for mathematical formulas) + - Text + - MathML + - HTML + +- **Convenient Operations**: + - One-click copy results + - Direct insertion into documents + - Dark theme support + +## 🚀 Quick Start + +### 1. Get API Keys +1. Visit [Mathpix OCR](https://mathpix.com/ocr) to register +2. Obtain your App ID and APP Key + +### 2. Configure Plugin +1. Click the ⚙️ icon in the top right corner +2. Enter your App ID and APP Key +3. Click "Save Credentials" +4. Select your preferred output formats (LaTeX and Text enabled by default) + +### 3. Using the Plugin + +#### Upload Images +- Click the upload area to select files +- Select multiple files at once for batch processing + +#### Recognition and Usage +1. Click the "Recognize" button to start processing +2. For each recognition result: + - View the preview + - Select output format from dropdown menu + - Edit recognition text if needed + - Use "Copy" to copy or "Insert" to add to document + +#### Important Notes +- **When using LaTeX format, some complex mathematical expressions may need manual adjustment to work with ONLYOFFICE Document Editor** +- Preview results before insertion to ensure accuracy +- If recognition results are unsatisfactory, try using clearer images + +## 💡 Usage Tips + +1. **Batch Processing**: + - Upload multiple images at once + - All images will show recognition results in sequence + +2. **Format Selection**: + - LaTeX: Best for mathematical formulas + - Text: Suitable for plain text content + - MathML: For XML format requirements + - HTML: For web-friendly format + +3. **Editing Features**: + - All recognition results are directly editable + - Make necessary modifications before document insertion + +## 🔧 System Requirements + +- ONLYOFFICE Document Editor +- Valid Mathpix API credentials +- Internet connection + +## 🆘 Common Issues + +1. **Recognition Failed?** + - Verify API credentials are correct + - Ensure image is clear and readable + - Check internet connection + +2. **Inserted Formula Displays Incorrectly?** + - Try using basic LaTeX syntax + - Check for unsupported advanced syntax + - Manually adjust complex expressions + +3. **How to Clear Everything?** + - Click the "Clear" button to reset plugin state + +## 📝 Feedback and Support + +If you encounter issues or have suggestions: +- Submit issues to our GitHub repository +- Contact ONLYOFFICE support team + +--- + +💪 Make mathematical formula input simple, enjoy efficient document editing! \ No newline at end of file diff --git a/sdkjs-plugins/content/mathpix/config.json b/sdkjs-plugins/content/mathpix/config.json new file mode 100644 index 00000000..05ce4dd3 --- /dev/null +++ b/sdkjs-plugins/content/mathpix/config.json @@ -0,0 +1,74 @@ +{ + "name": "Mathpix", + "nameLocale": { + "ru": "Mathpix", + "fr": "Mathpix", + "es": "Mathpix", + "pt-BR": "Mathpix", + "de": "Mathpix", + "zh-CN": "Mathpix" + }, + + "guid": "asc.{BFC5D9C6-89DE-4F28-9A3B-ABD8D2E48711}", + "version": "1.0.0", + "offered": "Svante", + + "variations" : [ + { + "description": "Perform OCR on mathematical formulas and text using Mathpix service.", + "descriptionLocale": { + "ru": "Выполняйте OCR математических формул и текста с помощью сервиса Mathpix.", + "fr": "Effectuez l'OCR des formules mathématiques et du texte à l'aide du service Mathpix.", + "es": "Realice OCR en fórmulas matemáticas y texto utilizando el servicio Mathpix.", + "pt-BR": "Realize OCR em fórmulas matemáticas e texto usando o serviço Mathpix.", + "de": "Führen Sie OCR für mathematische Formeln und Text mit dem Mathpix-Dienst durch.", + "zh-CN": "使用Mathpix服务对数学公式和文本进行OCR识别。" + }, + "url": "index.html", + "icons": "resources/%theme-type%(dark|light)/%scale%(default).%extension%(png)", + "icons2": [ + { + "style": "light", + "100%": { "normal": "resources/light/icon.png" }, + "125%": { "normal": "resources/light/icon@1.25x.png" }, + "150%": { "normal": "resources/light/icon@1.5x.png" }, + "175%": { "normal": "resources/light/icon@1.75x.png" }, + "200%": { "normal": "resources/light/icon@2x.png" } + }, + { + "style": "dark", + "100%": { "normal": "resources/dark/icon.png" }, + "125%": { "normal": "resources/dark/icon@1.25x.png" }, + "150%": { "normal": "resources/dark/icon@1.5x.png" }, + "175%": { "normal": "resources/dark/icon@1.75x.png" }, + "200%": { "normal": "resources/dark/icon@2x.png" } + } + ], + "isViewer": false, + "EditorsSupport": [ "word" ], + "initDataType": "text", + "initData": "", + "isVisual": true, + "isModal": false, + "isInsideMode": true, + "isUpdateOleOnResize": false, + "initOnSelectionChanged": false, + "size": [ 592, 100 ], + "store": { + "background": { + "light": "radial-gradient(circle, #B5BCC3 0%, #737D87 100%)", + "dark": "radial-gradient(circle, #B5BCC3 0%, #737D87 100%)" + }, + "screenshots": [ + "resources/store/screenshots/screenshot1.png", + "resources/store/screenshots/screenshot2.png" + ], + "icons": { + "light": "resources/store/icons", + "dark": "resources/store/icons" + }, + "categories": ["specAbilities", "work"] + } + } + ] +} \ No newline at end of file diff --git a/sdkjs-plugins/content/mathpix/deploy/mathpix.plugin b/sdkjs-plugins/content/mathpix/deploy/mathpix.plugin new file mode 100644 index 00000000..12c28c2a Binary files /dev/null and b/sdkjs-plugins/content/mathpix/deploy/mathpix.plugin differ diff --git a/sdkjs-plugins/content/mathpix/index.html b/sdkjs-plugins/content/mathpix/index.html new file mode 100644 index 00000000..0a195ebc --- /dev/null +++ b/sdkjs-plugins/content/mathpix/index.html @@ -0,0 +1,336 @@ + + + + + + Mathpix Plugin + + + + + + + +
+
+
+ +

Mathpix

+
+ + +
+

Configuration

+ + + + + +

+ Don't have an API key? + Register here +

+
+ +
+ + + + +
+
+ +
+

Click to upload

+
+ + +
+ + +
+ +
+ +
+

Results

+ +
+
+ + + + \ No newline at end of file diff --git a/sdkjs-plugins/content/mathpix/licenses/mathjax.license b/sdkjs-plugins/content/mathpix/licenses/mathjax.license new file mode 100644 index 00000000..255d173d --- /dev/null +++ b/sdkjs-plugins/content/mathpix/licenses/mathjax.license @@ -0,0 +1,19 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + Copyright (c) 2009-2023 The MathJax Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/sdkjs-plugins/content/mathpix/licenses/mathpix-api.license b/sdkjs-plugins/content/mathpix/licenses/mathpix-api.license new file mode 100644 index 00000000..c86cdb3b --- /dev/null +++ b/sdkjs-plugins/content/mathpix/licenses/mathpix-api.license @@ -0,0 +1,10 @@ +Mathpix API Terms of Service + +The Mathpix API is a proprietary service provided by Mathpix, Inc. Use of the API +is subject to the Terms of Service available at: +https://mathpix.com/terms + +and the Privacy Policy available at: +https://mathpix.com/privacy + +Copyright (c) Mathpix, Inc. All rights reserved. \ No newline at end of file diff --git a/sdkjs-plugins/content/mathpix/resources/dark/favicon.ico b/sdkjs-plugins/content/mathpix/resources/dark/favicon.ico new file mode 100644 index 00000000..cccdd7cb Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/dark/favicon.ico differ diff --git a/sdkjs-plugins/content/mathpix/resources/dark/icon.png b/sdkjs-plugins/content/mathpix/resources/dark/icon.png new file mode 100644 index 00000000..163002df Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/dark/icon.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/dark/icon@1.25x.png b/sdkjs-plugins/content/mathpix/resources/dark/icon@1.25x.png new file mode 100644 index 00000000..95638e5e Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/dark/icon@1.25x.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/dark/icon@1.5x.png b/sdkjs-plugins/content/mathpix/resources/dark/icon@1.5x.png new file mode 100644 index 00000000..5e7431eb Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/dark/icon@1.5x.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/dark/icon@1.75x.png b/sdkjs-plugins/content/mathpix/resources/dark/icon@1.75x.png new file mode 100644 index 00000000..35c21977 Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/dark/icon@1.75x.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/dark/icon@2x.png b/sdkjs-plugins/content/mathpix/resources/dark/icon@2x.png new file mode 100644 index 00000000..e5f2e90b Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/dark/icon@2x.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/light/favicon.ico b/sdkjs-plugins/content/mathpix/resources/light/favicon.ico new file mode 100644 index 00000000..cccdd7cb Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/light/favicon.ico differ diff --git a/sdkjs-plugins/content/mathpix/resources/light/icon.png b/sdkjs-plugins/content/mathpix/resources/light/icon.png new file mode 100644 index 00000000..163002df Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/light/icon.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/light/icon@1.25x.png b/sdkjs-plugins/content/mathpix/resources/light/icon@1.25x.png new file mode 100644 index 00000000..95638e5e Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/light/icon@1.25x.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/light/icon@1.5x.png b/sdkjs-plugins/content/mathpix/resources/light/icon@1.5x.png new file mode 100644 index 00000000..5e7431eb Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/light/icon@1.5x.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/light/icon@1.75x.png b/sdkjs-plugins/content/mathpix/resources/light/icon@1.75x.png new file mode 100644 index 00000000..35c21977 Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/light/icon@1.75x.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/light/icon@2x.png b/sdkjs-plugins/content/mathpix/resources/light/icon@2x.png new file mode 100644 index 00000000..e5f2e90b Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/light/icon@2x.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/store/icons/icon.png b/sdkjs-plugins/content/mathpix/resources/store/icons/icon.png new file mode 100644 index 00000000..163002df Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/store/icons/icon.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/store/icons/icon.svg b/sdkjs-plugins/content/mathpix/resources/store/icons/icon.svg new file mode 100644 index 00000000..39456676 --- /dev/null +++ b/sdkjs-plugins/content/mathpix/resources/store/icons/icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/sdkjs-plugins/content/mathpix/resources/store/icons/icon@1.25x.png b/sdkjs-plugins/content/mathpix/resources/store/icons/icon@1.25x.png new file mode 100644 index 00000000..95638e5e Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/store/icons/icon@1.25x.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/store/icons/icon@1.5x.png b/sdkjs-plugins/content/mathpix/resources/store/icons/icon@1.5x.png new file mode 100644 index 00000000..5e7431eb Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/store/icons/icon@1.5x.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/store/icons/icon@1.75x.png b/sdkjs-plugins/content/mathpix/resources/store/icons/icon@1.75x.png new file mode 100644 index 00000000..35c21977 Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/store/icons/icon@1.75x.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/store/icons/icon@2x.png b/sdkjs-plugins/content/mathpix/resources/store/icons/icon@2x.png new file mode 100644 index 00000000..e5f2e90b Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/store/icons/icon@2x.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/store/screenshots/screenshot1.png b/sdkjs-plugins/content/mathpix/resources/store/screenshots/screenshot1.png new file mode 100644 index 00000000..2ba60cc1 Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/store/screenshots/screenshot1.png differ diff --git a/sdkjs-plugins/content/mathpix/resources/store/screenshots/screenshot2.png b/sdkjs-plugins/content/mathpix/resources/store/screenshots/screenshot2.png new file mode 100644 index 00000000..fff6ff55 Binary files /dev/null and b/sdkjs-plugins/content/mathpix/resources/store/screenshots/screenshot2.png differ diff --git a/sdkjs-plugins/content/mathpix/scripts/code.js b/sdkjs-plugins/content/mathpix/scripts/code.js new file mode 100644 index 00000000..5fe55bd7 --- /dev/null +++ b/sdkjs-plugins/content/mathpix/scripts/code.js @@ -0,0 +1,438 @@ +/** + * + * (c) Copyright Ascensio System SIA 2020 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +(function () { + + const dropZone = document.getElementById('dropZone'); + const fileInput = document.getElementById('fileInput'); + const imageContainer = document.getElementById('imageContainer'); + const recognizeButton = document.getElementById('recognizeButton'); + const clearButton = document.getElementById('clearButton'); + const resultContainer = document.getElementById('resultContainer'); + const appIdInput = document.getElementById('appId'); + const appKeyInput = document.getElementById('appKey'); + const outputFormatCheckboxes = document.querySelectorAll('input[name="outputFormat"]'); + const errorContainer = document.getElementById('errorContainer'); + const configPanel = document.getElementById('configPanel'); + const settingsButton = document.getElementById('settingsButton'); + const saveCredentialsBtn = document.getElementById('saveCredentialsBtn'); + + let currentFiles = []; + let recognitionResults = []; + + function applyTranslations() { + var elements = document.getElementsByClassName("i18n"); + for (var i = 0; i < elements.length; i++) { + var el = elements[i]; + if (el.attributes["placeholder"]) { + el.attributes["placeholder"].value = window.Asc.plugin.tr(el.attributes["placeholder"].value); + } + if (el.attributes["title"]) { + el.attributes["title"].value = window.Asc.plugin.tr(el.attributes["title"].value); + } + if (el.innerText) { + el.innerText = window.Asc.plugin.tr(el.innerText); + } + } + } + + window.Asc.plugin.init = function () { + + const theme = window.Asc.plugin.theme; + if (theme) { + if (theme.type === 'dark') { + document.body.classList.add('dark-theme'); + } else { + document.body.classList.remove('dark-theme'); + } + } + + // Load saved credentials + appIdInput.value = localStorage.getItem('mathpixAppId') || ''; + appKeyInput.value = localStorage.getItem('mathpixAppKey') || ''; + + // Set up event listeners + dropZone.addEventListener('click', () => fileInput.click()); + dropZone.addEventListener('dragover', (e) => { + e.preventDefault(); + dropZone.classList.add('dragover'); + }); + dropZone.addEventListener('dragleave', () => dropZone.classList.remove('dragover')); + dropZone.addEventListener('drop', handleDrop); + fileInput.addEventListener('change', handleFileSelect); + document.addEventListener('paste', handlePaste); + recognizeButton.addEventListener('click', () => { + if (currentFiles.length > 0) { + recognizeFormulas(currentFiles); + } else { + showError('Please upload at least one image first.'); + } + }); + clearButton.addEventListener('click', clearAll); + settingsButton.addEventListener('click', toggleConfigPanel); + saveCredentialsBtn.addEventListener('click', saveCredentials); + + // Add translation support + window.Asc.plugin.onTranslate = applyTranslations; + + // Add theme change listener + window.Asc.plugin.onThemeChanged = function(theme) { + if (theme.type === 'dark') { + document.body.classList.add('dark-theme'); + } else { + document.body.classList.remove('dark-theme'); + } + }; + }; + + function handleDrop(e) { + e.preventDefault(); + dropZone.classList.remove('dragover'); + handleFiles(e.dataTransfer.files); + } + + function handleFileSelect(e) { + handleFiles(e.target.files); + } + + function handlePaste(e) { + const items = e.clipboardData.items; + for (let item of items) { + if (item.type.indexOf('image') !== -1) { + const blob = item.getAsFile(); + handleFiles([blob]); + break; + } + } + } + + function handleFiles(files) { + clearError(); + currentFiles = Array.from(files).filter(file => file.type.startsWith('image/')); + imageContainer.innerHTML = ''; + currentFiles.forEach((file, index) => { + const reader = new FileReader(); + reader.onload = (e) => { + const img = document.createElement('img'); + img.src = e.target.result; + img.className = 'image-preview'; + const div = document.createElement('div'); + div.className = 'image-item'; + div.appendChild(img); + imageContainer.appendChild(div); + }; + reader.readAsDataURL(file); + }); + recognizeButton.style.display = currentFiles.length > 0 ? 'inline-block' : 'none'; + clearButton.style.display = currentFiles.length > 0 ? 'inline-block' : 'none'; + + // Hide the upload section only if there are files + dropZone.style.display = currentFiles.length > 0 ? 'none' : 'flex'; + } + + function recognizeFormulas(files) { + clearError(); + const appId = appIdInput.value; + const appKey = appKeyInput.value; + if (!appId || !appKey) { + showError('Please enter both your Mathpix App ID and APP Key in the configuration panel.'); + toggleConfigPanel(); + return; + } + + resultContainer.innerHTML = '

Results

'; + recognitionResults = []; + + files.forEach((file, index) => { + const formData = new FormData(); + formData.append('file', file); + formData.append('formats', JSON.stringify(["text", "data", "html", "latex_styled"])); + formData.append('data_options', JSON.stringify({ + include_latex: true, + include_mathml: true, + })); + formData.append('ocr', JSON.stringify(["math", "text"])); + + fetch('https://api.mathpix.com/v3/text', { + method: 'POST', + headers: { + 'app_id': appId, + 'app_key': appKey + }, + body: formData + }) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.json(); + }) + .then(data => { + if (data.error) { + showError(`API Error for image ${index + 1}: ${data.error}`); + return; + } + recognitionResults[index] = data; + displayResult(data, index); + }) + .catch(error => { + showError(`Network Error for image ${index + 1}: ${error.message}`); + }); + }); + + resultContainer.style.display = 'block'; + } + + function displayResult(data, index) { + const resultBox = document.createElement('div'); + resultBox.className = 'result-box'; + + // When the LaTeX result is 'No LaTeX result', the 'Text' option will be selected by default + const latexResult = data.latex_styled || data.data?.find(item => item.type === 'latex')?.value; + const isNoLatexResult = !latexResult || latexResult === 'No LaTeX result'; + + resultBox.innerHTML = ` +

Image ${index + 1}

+
+ +
+ + + `; + resultContainer.appendChild(resultBox); + + applyTranslations(); + + const previewContainer = resultBox.querySelector('.preview-container'); + let htmlContent = data.html || window.Asc.plugin.tr('No preview available'); + htmlContent = htmlContent.replace(/(.*?)<\/latex>/g, '\\($1\\)'); + htmlContent = htmlContent.replace(/(.*?)<\/latex>/g, '\\($1\\)'); + previewContainer.innerHTML = htmlContent; + MathJax.typesetPromise([previewContainer]).catch((err) => console.log('MathJax error:', err)); + + const formatSelector = resultBox.querySelector('.formatSelector'); + formatSelector.addEventListener('change', () => { + updateCodeDisplay(index); + // Add warning message for LaTeX format + if (formatSelector.value === 'latex') { + const warningDiv = resultBox.querySelector('.latex-warning') || document.createElement('div'); + warningDiv.className = 'latex-warning'; + warningDiv.innerHTML = ` +
+ ⚠️ + ${window.Asc.plugin.tr('Note: Some advanced LaTeX syntax may not be compatible with Document Editor. Manual adjustment might be needed.')} +
`; + warningDiv.style.cssText = ` + color: #DDAA00; + font-size: 10px; + margin-top: 6px; + padding: 6px 10px; + background-color: rgba(221, 170, 0, 0.1); + border-radius: 3px; + `; + + const codeDisplay = resultBox.querySelector('.codeDisplay'); + if (!resultBox.querySelector('.latex-warning')) { + codeDisplay.parentNode.insertBefore(warningDiv, codeDisplay); + } + } else { + const warningDiv = resultBox.querySelector('.latex-warning'); + if (warningDiv) { + warningDiv.remove(); + } + } + }); + + const copyCodeBtn = resultBox.querySelector('.copyCodeBtn'); + copyCodeBtn.addEventListener('click', () => copyCode(index)); + + const insertCodeBtn = resultBox.querySelector('.insertCodeBtn'); + insertCodeBtn.addEventListener('click', () => insertCode(index)); + + updateCodeDisplay(index); + + // Trigger the change event to show warning if LaTeX is initially selected + if (formatSelector.value === 'latex') { + formatSelector.dispatchEvent(new Event('change')); + } + } + + // Per the official request of ONLYOFFICE, perform LaTeX conversion: + // better format for latex formula is this: + // \\sum{csc}{\\rightarrow\\above{yelds}}\\begin{matrix}1&0&0\\\\0&1&0\\\\0&0&1\\\\\\end{matrix} + function convertLatex(code) { + // Replace \sum \csc with \sum{csc} + code = code.replace( + /\\sum\s+\\csc/g, + '\\sum{csc}' + ); + + // Replace \xrightarrow{\text{yields}} with {\rightarrow\above{yields}} + code = code.replace( + /\\xrightarrow{\\text\s*{([^}]+)}}/g, + '{\\rightarrow\\above{$1}}' + ); + + // Add more replacements here as needed + + return code; + } + + function updateCodeDisplay(index) { + const resultBox = resultContainer.children[index + 1]; + const formatSelector = resultBox.querySelector('.formatSelector'); + const codeDisplay = resultBox.querySelector('.codeDisplay'); + const data = recognitionResults[index]; + + if (!data) return; + + const format = formatSelector.value; + let code = ''; + + switch (format) { + case 'latex': + code = data.latex_styled || data.data?.find(item => item.type === 'latex')?.value || 'No LaTeX result'; + code = convertLatex(code); + break; + case 'mathml': + code = data.data?.find(item => item.type === 'mathml')?.value || 'No MathML result'; + break; + case 'text': + code = data.text || 'No Text result'; + break; + case 'html': + code = data.html || 'No HTML result'; + break; + } + + codeDisplay.innerText = code; + } + + function copyCode(index) { + const resultBox = resultContainer.children[index + 1]; + const codeDisplay = resultBox.querySelector('.codeDisplay'); + const code = codeDisplay.innerText; + navigator.clipboard.writeText(code).then(() => { + alert('Code copied to clipboard!'); + }); + } + + function insertCode(index) { + clearError(); + const resultBox = resultContainer.children[index + 1]; + const formatSelector = resultBox.querySelector('.formatSelector'); + const codeDisplay = resultBox.querySelector('.codeDisplay'); + const format = formatSelector.value; + const code = codeDisplay.innerText; + + if (format === 'latex') { + // Proceed with insertion + Asc.scope.text = code; + window.Asc.plugin.callCommand(function() { + try { + Api.GetDocument().AddMathEquation(Asc.scope.text, "latex"); + } catch (error) { + console.error("Error inserting LaTeX equation:", error); + } + }, false); + } else { + window.Asc.plugin.executeMethod("PasteText", [code], function(result) { + if (result !== true) { + console.error("Failed to insert text"); + } + }); + } + } + + function saveCredentials() { + const appId = appIdInput.value; + const appKey = appKeyInput.value; + localStorage.setItem('mathpixAppId', appId); + localStorage.setItem('mathpixAppKey', appKey); + alert('Credentials saved!'); + toggleConfigPanel(); + } + + function toggleConfigPanel() { + configPanel.style.display = configPanel.style.display === 'none' ? 'block' : 'none'; + } + + function showError(message) { + errorContainer.classList.add('i18n'); + errorContainer.textContent = window.Asc.plugin.tr(message); + errorContainer.style.display = 'block'; + } + + function clearError() { + errorContainer.style.display = 'none'; + } + + function clearAll() { + clearError(); + currentFiles = []; + recognitionResults = []; + imageContainer.innerHTML = ''; + resultContainer.innerHTML = '

Results

'; + applyTranslations(); + + resultContainer.style.display = 'none'; + recognizeButton.style.display = 'none'; + clearButton.style.display = 'none'; + errorContainer.style.display = 'none'; + + dropZone.style.display = 'flex'; + fileInput.value = ''; + } + + // Default to only select latex and text + outputFormatCheckboxes.forEach((checkbox) => { + checkbox.checked = checkbox.value === 'latex' || checkbox.value === 'text'; + }); + + // Add checkbox change event listener + outputFormatCheckboxes.forEach(checkbox => { + checkbox.addEventListener('change', () => { + // If there are displayed results, update all result format selectors + const resultBoxes = document.querySelectorAll('.result-box'); + resultBoxes.forEach((box, index) => { + const formatSelector = box.querySelector('.formatSelector'); + const currentValue = formatSelector.value; + + // Rebuild options + formatSelector.innerHTML = Array.from(outputFormatCheckboxes) + .filter(checkbox => checkbox.checked) + .map(checkbox => ``) + .join(''); + + // If the previously selected format is still available, keep it selected + if (Array.from(formatSelector.options).some(option => option.value === currentValue)) { + formatSelector.value = currentValue; + } + + // Update displayed code + updateCodeDisplay(index); + }); + }); + }); + +})(); \ No newline at end of file diff --git a/sdkjs-plugins/content/mathpix/translations/de-DE.json b/sdkjs-plugins/content/mathpix/translations/de-DE.json new file mode 100644 index 00000000..0f9585ed --- /dev/null +++ b/sdkjs-plugins/content/mathpix/translations/de-DE.json @@ -0,0 +1,22 @@ +{ + "Click to upload": "Zum Hochladen klicken", + "Results": "Ergebnisse", + "Configuration": "Konfiguration", + "Mathpix App ID:": "Mathpix App-ID:", + "Mathpix APP Key:": "Mathpix APP-Schlüssel:", + "Enter your App ID": "Geben Sie Ihre App-ID ein", + "Enter your APP Key": "Geben Sie Ihren APP-Schlüssel ein", + "Save Credentials": "Anmeldedaten speichern", + "Don't have an API key?": "Sie haben noch keinen API-Schlüssel?", + "Register here": "Hier registrieren", + "Output Formats:": "Ausgabeformate:", + "Recognize": "Erkennen", + "Clear": "Löschen", + "Copy": "Kopieren", + "Insert": "Einfügen", + "Image": "Bild", + "No preview available": "Keine Vorschau verfügbar", + "Credentials saved!": "Anmeldedaten gespeichert!", + "Please enter both your Mathpix App ID and APP Key in the configuration panel.": "Bitte geben Sie sowohl Ihre Mathpix App-ID als auch den APP-Schlüssel im Konfigurationsbereich ein.", + "Note: Some advanced LaTeX syntax may not be compatible with Document Editor. Manual adjustment might be needed.": "Hinweis: Einige erweiterte LaTeX-Syntax ist möglicherweise nicht mit dem Dokumenten-Editor kompatibel. Manuelle Anpassung könnte erforderlich sein." +} \ No newline at end of file diff --git a/sdkjs-plugins/content/mathpix/translations/es-ES.json b/sdkjs-plugins/content/mathpix/translations/es-ES.json new file mode 100644 index 00000000..e76f3f93 --- /dev/null +++ b/sdkjs-plugins/content/mathpix/translations/es-ES.json @@ -0,0 +1,22 @@ +{ + "Click to upload": "Haga clic para cargar", + "Results": "Resultados", + "Configuration": "Configuración", + "Mathpix App ID:": "ID de la aplicación Mathpix:", + "Mathpix APP Key:": "Clave APP de Mathpix:", + "Enter your App ID": "Ingrese su ID de aplicación", + "Enter your APP Key": "Ingrese su clave APP", + "Save Credentials": "Guardar credenciales", + "Don't have an API key?": "¿No tiene una clave API?", + "Register here": "Regístrese aquí", + "Output Formats:": "Formatos de salida:", + "Recognize": "Reconocer", + "Clear": "Limpiar", + "Copy": "Copiar", + "Insert": "Insertar", + "Image": "Imagen", + "No preview available": "Vista previa no disponible", + "Credentials saved!": "¡Credenciales guardadas!", + "Please enter both your Mathpix App ID and APP Key in the configuration panel.": "Por favor, ingrese tanto su ID de aplicación Mathpix como su clave APP en el panel de configuración.", + "Note: Some advanced LaTeX syntax may not be compatible with Document Editor. Manual adjustment might be needed.": "Nota: Algunas sintaxis LaTeX avanzadas pueden no ser compatibles con el Editor de documentos. Puede ser necesario un ajuste manual." +} \ No newline at end of file diff --git a/sdkjs-plugins/content/mathpix/translations/fr-FR.json b/sdkjs-plugins/content/mathpix/translations/fr-FR.json new file mode 100644 index 00000000..1975fed8 --- /dev/null +++ b/sdkjs-plugins/content/mathpix/translations/fr-FR.json @@ -0,0 +1,22 @@ +{ + "Click to upload": "Cliquez pour télécharger", + "Results": "Résultats", + "Configuration": "Configuration", + "Mathpix App ID:": "ID d'application Mathpix :", + "Mathpix APP Key:": "Clé APP Mathpix :", + "Enter your App ID": "Entrez votre ID d'application", + "Enter your APP Key": "Entrez votre clé APP", + "Save Credentials": "Enregistrer les identifiants", + "Don't have an API key?": "Vous n'avez pas de clé API ?", + "Register here": "Inscrivez-vous ici", + "Output Formats:": "Formats de sortie :", + "Recognize": "Reconnaître", + "Clear": "Effacer", + "Copy": "Copier", + "Insert": "Insérer", + "Image": "Image", + "No preview available": "Aucun aperçu disponible", + "Credentials saved!": "Identifiants enregistrés !", + "Please enter both your Mathpix App ID and APP Key in the configuration panel.": "Veuillez saisir votre ID d'application Mathpix et votre clé APP dans le panneau de configuration.", + "Note: Some advanced LaTeX syntax may not be compatible with Document Editor. Manual adjustment might be needed.": "Remarque : Certaines syntaxes LaTeX avancées peuvent ne pas être compatibles avec l'Éditeur de documents. Un ajustement manuel peut être nécessaire." +} \ No newline at end of file diff --git a/sdkjs-plugins/content/mathpix/translations/langs.json b/sdkjs-plugins/content/mathpix/translations/langs.json new file mode 100644 index 00000000..d714e840 --- /dev/null +++ b/sdkjs-plugins/content/mathpix/translations/langs.json @@ -0,0 +1,8 @@ +[ + "ru-RU", + "de-DE", + "fr-FR", + "es-ES", + "pt-BR", + "zh-CN" +] \ No newline at end of file diff --git a/sdkjs-plugins/content/mathpix/translations/pt-BR.json b/sdkjs-plugins/content/mathpix/translations/pt-BR.json new file mode 100644 index 00000000..48000d66 --- /dev/null +++ b/sdkjs-plugins/content/mathpix/translations/pt-BR.json @@ -0,0 +1,22 @@ +{ + "Click to upload": "Clique para fazer upload", + "Results": "Resultados", + "Configuration": "Configuração", + "Mathpix App ID:": "ID do aplicativo Mathpix:", + "Mathpix APP Key:": "Chave do aplicativo Mathpix:", + "Enter your App ID": "Digite seu ID do aplicativo", + "Enter your APP Key": "Digite sua chave do aplicativo", + "Save Credentials": "Salvar credenciais", + "Don't have an API key?": "Não tem uma chave API?", + "Register here": "Registre-se aqui", + "Output Formats:": "Formatos de saída:", + "Recognize": "Reconhecer", + "Clear": "Limpar", + "Copy": "Copiar", + "Insert": "Inserir", + "Image": "Imagem", + "No preview available": "Nenhuma prévia disponível", + "Credentials saved!": "Credenciais salvas!", + "Please enter both your Mathpix App ID and APP Key in the configuration panel.": "Por favor, insira seu ID do aplicativo Mathpix e a Chave APP no painel de configuração.", + "Note: Some advanced LaTeX syntax may not be compatible with Document Editor. Manual adjustment might be needed.": "Nota: Algumas sintaxes LaTeX avançadas podem não ser compatíveis com o Editor de Documentos. Pode ser necessário ajuste manual." +} \ No newline at end of file diff --git a/sdkjs-plugins/content/mathpix/translations/ru-RU.json b/sdkjs-plugins/content/mathpix/translations/ru-RU.json new file mode 100644 index 00000000..d2317c62 --- /dev/null +++ b/sdkjs-plugins/content/mathpix/translations/ru-RU.json @@ -0,0 +1,22 @@ +{ + "Click to upload": "Нажмите для загрузки", + "Results": "Результаты", + "Configuration": "Конфигурация", + "Mathpix App ID:": "ID приложения Mathpix:", + "Mathpix APP Key:": "Ключ приложения Mathpix:", + "Enter your App ID": "Введите ID приложения", + "Enter your APP Key": "Введите ключ приложения", + "Save Credentials": "Сохранить учетные данные", + "Don't have an API key?": "Нет ключа API?", + "Register here": "Зарегистрируйтесь здесь", + "Output Formats:": "Форматы вывода:", + "Recognize": "Распознать", + "Clear": "Очистить", + "Copy": "Копировать", + "Insert": "Вставить", + "Image": "Изображение", + "No preview available": "Предпросмотр недоступен", + "Credentials saved!": "Учетные данные сохранены!", + "Please enter both your Mathpix App ID and APP Key in the configuration panel.": "Пожалуйста, введите ID приложения Mathpix и ключ приложения в панели конфигурации.", + "Note: Some advanced LaTeX syntax may not be compatible with Document Editor. Manual adjustment might be needed.": "Примечание: Некоторые расширенные синтаксисы LaTeX могут быть несовместимы с Редактором документов. Может потребоваться ручная настройка." +} \ No newline at end of file diff --git a/sdkjs-plugins/content/mathpix/translations/zh-CN.json b/sdkjs-plugins/content/mathpix/translations/zh-CN.json new file mode 100644 index 00000000..13d608b4 --- /dev/null +++ b/sdkjs-plugins/content/mathpix/translations/zh-CN.json @@ -0,0 +1,22 @@ +{ + "Click to upload": "点击上传", + "Results": "结果", + "Configuration": "配置", + "Mathpix App ID:": "Mathpix 应用 ID:", + "Mathpix APP Key:": "Mathpix 应用密钥:", + "Enter your App ID": "请输入应用 ID", + "Enter your APP Key": "请输入应用密钥", + "Save Credentials": "保存凭据", + "Don't have an API key?": "没有 API 密钥?", + "Register here": "在此注册", + "Output Formats:": "输出格式:", + "Recognize": "识别", + "Clear": "清除", + "Copy": "复制", + "Insert": "插入", + "Image": "图片", + "No preview available": "预览不可用", + "Credentials saved!": "凭据已保存!", + "Please enter both your Mathpix App ID and APP Key in the configuration panel.": "请在配置面板中输入您的 Mathpix 应用 ID 和应用密钥。", + "Note: Some advanced LaTeX syntax may not be compatible with Document Editor. Manual adjustment might be needed.": "注意:某些高级 LaTeX 语法可能与文档编辑器不兼容。可能需要手动调整。" +} \ No newline at end of file diff --git a/store/config.json b/store/config.json index c77a7478..a0a8e573 100644 --- a/store/config.json +++ b/store/config.json @@ -35,5 +35,6 @@ { "name": "onlydraw", "discussion": "" }, { "name": "pomodoro", "discussion": "" }, { "name": "videoembedder", "discussion": "" }, - { "name": "mathtype", "discussion": "" } + { "name": "mathtype", "discussion": "" }, + { "name": "mathpix", "discussion": "" } ]