@ -3,7 +3,7 @@
|
||||
"Check": "Prüfen",
|
||||
"Insert to document": "In Dokument einfügen",
|
||||
"Dismiss": "Überspringen",
|
||||
"Clear": "Löschen",
|
||||
"Clear": "Leeren",
|
||||
"Language": "Sprache",
|
||||
"Select the text to check in the document or enter it manually": "Wählen Sie den zu prüfenden Text im Dokument aus oder geben Sie ihn manuell ein",
|
||||
"Possible mistakes found": "Mögliche Fehler gefunden: ",
|
||||
|
||||
14
sdkjs-plugins/content/mathpix/3rd-Party.txt
Normal file
@ -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
|
||||
|
||||
7
sdkjs-plugins/content/mathpix/CHANGELOG.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Change Log
|
||||
|
||||
## 1.0.0
|
||||
|
||||
* Initial release.
|
||||
|
||||
|
||||
103
sdkjs-plugins/content/mathpix/README.md
Normal file
@ -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!
|
||||
74
sdkjs-plugins/content/mathpix/config.json
Normal file
@ -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"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
sdkjs-plugins/content/mathpix/deploy/mathpix.plugin
Normal file
336
sdkjs-plugins/content/mathpix/index.html
Normal file
@ -0,0 +1,336 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Mathpix Plugin</title>
|
||||
<script type="text/javascript" src="https://onlyoffice.github.io/sdkjs-plugins/v1/plugins.js"></script>
|
||||
<script type="text/javascript" src="https://onlyoffice.github.io/sdkjs-plugins/v1/plugins-ui.js"></script>
|
||||
<link rel="stylesheet" href="https://onlyoffice.github.io/sdkjs-plugins/v1/plugins.css">
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f5f5f5;
|
||||
color: #333;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
#scrollable-container {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.logo {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 16px;
|
||||
color: #2c3e50;
|
||||
margin: 0;
|
||||
}
|
||||
#dropZone {
|
||||
border: 2px dashed #3498db;
|
||||
border-radius: 8px;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
#dropZone:hover, #dropZone.dragover {
|
||||
background-color: #ecf0f1;
|
||||
}
|
||||
.image-preview {
|
||||
max-width: 100%;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.result-box {
|
||||
background-color: #f9f9f9;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.preview-container {
|
||||
overflow-x: auto;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
margin-bottom: 15px;
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
button {
|
||||
background-color: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 15px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
margin-right: 10px;
|
||||
}
|
||||
button:hover {
|
||||
background-color: #2980b9;
|
||||
}
|
||||
input[type="text"], select, textarea {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.error {
|
||||
color: #e74c3c;
|
||||
background-color: #fadbd8;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
margin: 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
#resultContainer {
|
||||
display: none;
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
padding-right: 10px;
|
||||
}
|
||||
#recognizeButton, #clearButton {
|
||||
display: none;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.formatSelector {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.codeDisplay {
|
||||
width: 100%;
|
||||
min-height: 150px;
|
||||
max-height: 300px;
|
||||
margin-bottom: 10px;
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
background-color: #ffffff;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
resize: vertical;
|
||||
outline: none;
|
||||
}
|
||||
.codeDisplay:focus {
|
||||
border-color: #3498db;
|
||||
box-shadow: 0 0 5px rgba(52, 152, 219, 0.3);
|
||||
}
|
||||
#errorContainer {
|
||||
display: none;
|
||||
}
|
||||
#insertArea {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
#imageContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.image-item {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
#configPanel {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
right: 10px;
|
||||
background-color: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.1);
|
||||
z-index: 1000;
|
||||
}
|
||||
#settingsButton {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
font-size: 16px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-color: #f1f1f1;
|
||||
color: #333;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
#settingsButton:hover {
|
||||
background-color: #e1e1e1;
|
||||
}
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.checkbox-group label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
/* Add dark theme styles */
|
||||
body.dark-theme {
|
||||
background-color: #2d2d2d;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.dark-theme .container {
|
||||
background-color: #363636;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.dark-theme h1, .dark-theme h2, .dark-theme h3 {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.dark-theme #dropZone {
|
||||
border-color: #4a9eff;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.dark-theme #dropZone:hover, .dark-theme #dropZone.dragover {
|
||||
background-color: #404040;
|
||||
}
|
||||
|
||||
.dark-theme .result-box {
|
||||
background-color: #404040;
|
||||
border-color: #505050;
|
||||
}
|
||||
|
||||
.dark-theme .preview-container {
|
||||
background-color: #363636;
|
||||
border-color: #505050;
|
||||
}
|
||||
|
||||
.dark-theme .codeDisplay {
|
||||
background-color: #2d2d2d;
|
||||
border-color: #505050;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.dark-theme .codeDisplay:focus {
|
||||
border-color: #4a9eff;
|
||||
}
|
||||
|
||||
.dark-theme #configPanel {
|
||||
background-color: #363636;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.dark-theme #settingsButton {
|
||||
background-color: #404040;
|
||||
color: #ffffff;
|
||||
border-color: #505050;
|
||||
}
|
||||
|
||||
.dark-theme #settingsButton:hover {
|
||||
background-color: #505050;
|
||||
}
|
||||
|
||||
.dark-theme input[type="text"],
|
||||
.dark-theme select,
|
||||
.dark-theme textarea {
|
||||
background-color: #2d2d2d;
|
||||
border-color: #505050;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.dark-theme .error {
|
||||
background-color: #662c2c;
|
||||
color: #ff9999;
|
||||
}
|
||||
</style>
|
||||
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="scrollable-container">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="resources/dark/favicon.ico" alt="Mathpix Logo" class="logo">
|
||||
<h1 class="i18n">Mathpix</h1>
|
||||
</div>
|
||||
|
||||
<button id="settingsButton" aria-label="Settings" class="i18n">⚙️</button>
|
||||
<div id="configPanel">
|
||||
<h3 class="i18n">Configuration</h3>
|
||||
<label for="appId" class="i18n">Mathpix App ID:</label>
|
||||
<input type="text" id="appId" placeholder="Enter your App ID" class="i18n">
|
||||
<label for="appKey" class="i18n">Mathpix APP Key:</label>
|
||||
<input type="text" id="appKey" placeholder="Enter your APP Key" class="i18n">
|
||||
<button id="saveCredentialsBtn" style="padding: 5px 10px; font-size: 14px;" class="i18n">Save Credentials</button>
|
||||
<p>
|
||||
<span class="i18n">Don't have an API key?</span>
|
||||
<a href="https://mathpix.com/ocr" target="_blank" class="i18n">Register here</a>
|
||||
</p>
|
||||
<br>
|
||||
<label class="i18n">Output Formats:</label>
|
||||
<div class="checkbox-group">
|
||||
<label><input type="checkbox" name="outputFormat" value="latex" checked> <span class="i18n">LaTeX</span></label>
|
||||
<label><input type="checkbox" name="outputFormat" value="text" checked> <span class="i18n">Text</span></label>
|
||||
<label><input type="checkbox" name="outputFormat" value="mathml"> <span class="i18n">MathML</span></label>
|
||||
<label><input type="checkbox" name="outputFormat" value="html"> <span class="i18n">HTML</span></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="dropZone">
|
||||
<p class="i18n">Click to upload</p>
|
||||
</div>
|
||||
<input type="file" id="fileInput" accept="image/*" multiple style="display: none;">
|
||||
|
||||
<div id="imageContainer"></div>
|
||||
<button id="recognizeButton" class="i18n">Recognize</button>
|
||||
<button id="clearButton" class="i18n">Clear</button>
|
||||
</div>
|
||||
|
||||
<div id="errorContainer" class="error"></div>
|
||||
|
||||
<div id="resultContainer" class="container">
|
||||
<h2 class="i18n">Results</h2>
|
||||
<!-- Results will be dynamically added here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="scripts/code.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
19
sdkjs-plugins/content/mathpix/licenses/mathjax.license
Normal file
@ -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.
|
||||
10
sdkjs-plugins/content/mathpix/licenses/mathpix-api.license
Normal file
@ -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.
|
||||
BIN
sdkjs-plugins/content/mathpix/resources/dark/icon.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
sdkjs-plugins/content/mathpix/resources/dark/icon@1.25x.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
sdkjs-plugins/content/mathpix/resources/dark/icon@1.5x.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
sdkjs-plugins/content/mathpix/resources/dark/icon@1.75x.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
sdkjs-plugins/content/mathpix/resources/dark/icon@2x.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
sdkjs-plugins/content/mathpix/resources/light/icon.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
sdkjs-plugins/content/mathpix/resources/light/icon@1.25x.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
sdkjs-plugins/content/mathpix/resources/light/icon@1.5x.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
sdkjs-plugins/content/mathpix/resources/light/icon@1.75x.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
sdkjs-plugins/content/mathpix/resources/light/icon@2x.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
sdkjs-plugins/content/mathpix/resources/store/icons/icon.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="48" height="48">
|
||||
<path d="M0 0 C0.8245166 -0.00478363 1.6490332 -0.00956726 2.49853516 -0.01449585 C4.23667313 -0.01788872 5.97487544 -0.00872903 7.71289062 0.01220703 C10.36733825 0.03898521 13.01755825 0.01244254 15.671875 -0.01953125 C17.36459263 -0.01622704 19.05730763 -0.00982056 20.75 0 C21.93456787 -0.01518173 21.93456787 -0.01518173 23.14306641 -0.03067017 C27.11276955 0.05339275 28.99170918 0.40801499 32.37255859 2.66650391 C35.0441572 6.66575868 35.09944932 9.57732793 35.0390625 14.2890625 C35.04384613 15.1135791 35.04862976 15.9380957 35.05355835 16.78759766 C35.05695122 18.52573563 35.04779153 20.26393794 35.02685547 22.00195312 C35.00007729 24.65640075 35.02661996 27.30662075 35.05859375 29.9609375 C35.05528954 31.65365513 35.04888306 33.34637013 35.0390625 35.0390625 C35.04918365 35.82877441 35.05930481 36.61848633 35.06973267 37.43212891 C34.98566975 41.40183205 34.63104751 43.28077168 32.37255859 46.66162109 C28.37330382 49.3332197 25.46173457 49.38851182 20.75 49.328125 C19.5132251 49.33530045 19.5132251 49.33530045 18.25146484 49.34262085 C16.51332687 49.34601372 14.77512456 49.33685403 13.03710938 49.31591797 C10.38266175 49.28913979 7.73244175 49.31568246 5.078125 49.34765625 C3.38540737 49.34435204 1.69269237 49.33794556 0 49.328125 C-0.78971191 49.33824615 -1.57942383 49.34836731 -2.39306641 49.35879517 C-6.36276955 49.27473225 -8.24170918 48.92011001 -11.62255859 46.66162109 C-14.2941572 42.66236632 -14.34944932 39.75079707 -14.2890625 35.0390625 C-14.29384613 34.2145459 -14.29862976 33.3900293 -14.30355835 32.54052734 C-14.30695122 30.80238937 -14.29779153 29.06418706 -14.27685547 27.32617188 C-14.25007729 24.67172425 -14.27661996 22.02150425 -14.30859375 19.3671875 C-14.30528954 17.67446987 -14.29888306 15.98175487 -14.2890625 14.2890625 C-14.29918365 13.49935059 -14.30930481 12.70963867 -14.31973267 11.89599609 C-14.23566975 7.92629295 -13.88104751 6.04735332 -11.62255859 2.66650391 C-7.62330382 -0.0050947 -4.71173457 -0.06038682 0 0 Z " fill="#0293FE" transform="translate(13.625,-0.6640625)"/>
|
||||
<path d="M0 0 C3.53571429 0.53571429 3.53571429 0.53571429 5 2 C5.07226502 3.85287502 5.0838122 5.70833878 5.0625 7.5625 C5.05347656 8.57441406 5.04445313 9.58632813 5.03515625 10.62890625 C5.02355469 11.41136719 5.01195312 12.19382812 5 13 C6.98 13 8.96 13 11 13 C10.98839844 12.21753906 10.97679687 11.43507813 10.96484375 10.62890625 C10.95582031 9.61699219 10.94679688 8.60507812 10.9375 7.5625 C10.92589844 6.55316406 10.91429687 5.54382813 10.90234375 4.50390625 C11 2 11 2 12 1 C14.5 0.875 14.5 0.875 17 1 C18 2 18 2 18.11352539 4.31665039 C18.10828857 5.31688232 18.10305176 6.31711426 18.09765625 7.34765625 C18.09443359 8.42724609 18.09121094 9.50683594 18.08789062 10.61914062 C18.07951172 11.75544922 18.07113281 12.89175781 18.0625 14.0625 C18.05798828 15.20267578 18.05347656 16.34285156 18.04882812 17.51757812 C18.03699747 20.34510351 18.0205141 23.1725264 18 26 C19.98 26 21.96 26 24 26 C24 17.42 24 8.84 24 0 C31.98540928 6.84463652 31.98540928 6.84463652 32.19287109 9.05371094 C32.27999481 11.95255448 32.33462199 14.85012448 32.375 17.75 C32.43107422 19.25433594 32.43107422 19.25433594 32.48828125 20.7890625 C32.54241297 25.32409765 32.47428005 28.18809686 30.15625 32.15625 C25.50693792 34.87218478 21.4224267 34.80598337 16.125 34.75 C14.67287109 34.80414063 14.67287109 34.80414063 13.19140625 34.859375 C7.80372037 34.859375 4.72579152 34.37160752 0.8046875 30.515625 C-2 27.29216779 -2 27.29216779 -2 26 C2.29 26 6.58 26 11 26 C11 24.02 11 22.04 11 20 C10.22914062 20.02320312 9.45828125 20.04640625 8.6640625 20.0703125 C7.66117188 20.08835937 6.65828125 20.10640625 5.625 20.125 C4.62726562 20.14820312 3.62953125 20.17140625 2.6015625 20.1953125 C0 20 0 20 -2 18 C-2.19852102 15.29077199 -2.27839477 12.70696821 -2.25 10 C-2.25773438 9.26265625 -2.26546875 8.5253125 -2.2734375 7.765625 C-2.2533196 2.2533196 -2.2533196 2.2533196 0 0 Z " fill="#236AED" transform="translate(16,14)"/>
|
||||
<path d="M0 0 C0.66 -0.33 1.32 -0.66 2 -1 C7.26883876 -1.59873168 9.8846468 -0.25400021 14 3 C15.35700647 5.71401294 15.1123861 7.84846316 15.09765625 10.8828125 C15.09443359 12.04941406 15.09121094 13.21601563 15.08789062 14.41796875 C15.07532227 16.25294922 15.07532227 16.25294922 15.0625 18.125 C15.05798828 19.35605469 15.05347656 20.58710938 15.04882812 21.85546875 C15.0370133 24.90369392 15.02054028 27.95182314 15 31 C13.02 31 11.04 31 9 31 C8.505 19.12 8.505 19.12 8 7 C6.35 7 4.7 7 3 7 C2.67 10.63 2.34 14.26 2 18 C0.02 18 -1.96 18 -4 18 C-4.33 14.37 -4.66 10.74 -5 7 C-6.32 6.67 -7.64 6.34 -9 6 C-10.82116003 7.82116003 -10.1323508 10.30671764 -10.13671875 12.7265625 C-10.13285156 13.47679687 -10.12898437 14.22703125 -10.125 15 C-10.12886719 15.75023438 -10.13273438 16.50046875 -10.13671875 17.2734375 C-10.47675541 20.93606117 -10.47675541 20.93606117 -9 24 C-7.15108054 24.23363881 -5.29511969 24.41303635 -3.4375 24.5625 C-2.42558594 24.64628906 -1.41367187 24.73007812 -0.37109375 24.81640625 C0.80259766 24.90728516 0.80259766 24.90728516 2 25 C2 26.98 2 28.96 2 31 C-9.57983353 31.76294657 -9.57983353 31.76294657 -12.94140625 29.95703125 C-17.56339285 25.2522628 -17.24348294 20.87602966 -17.3125 14.6875 C-17.34150391 13.83220703 -17.37050781 12.97691406 -17.40039062 12.09570312 C-17.44288075 7.87610668 -17.38274023 5.61475183 -15.10546875 1.95703125 C-10.61291069 -2.2187973 -5.65466149 -1.46602335 0 0 Z " fill="#F6FAFE" transform="translate(25,9)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
BIN
sdkjs-plugins/content/mathpix/resources/store/icons/icon@2x.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 62 KiB |
438
sdkjs-plugins/content/mathpix/scripts/code.js
Normal file
@ -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 = '<h2>Results</h2>';
|
||||
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 = `
|
||||
<h3 class="i18n">Image ${index + 1}</h3>
|
||||
<div class="preview-container"></div>
|
||||
<select class="formatSelector">
|
||||
${Array.from(outputFormatCheckboxes)
|
||||
.filter(checkbox => checkbox.checked)
|
||||
.map(checkbox =>
|
||||
`<option value="${checkbox.value}" class="i18n" ${isNoLatexResult && checkbox.value === 'text' ? 'selected' : ''}>${checkbox.value.charAt(0).toUpperCase() + checkbox.value.slice(1)}</option>`
|
||||
).join('')}
|
||||
</select>
|
||||
<div class="codeDisplay" contenteditable="true" spellcheck="false"></div>
|
||||
<button class="copyCodeBtn i18n">Copy</button>
|
||||
<button class="insertCodeBtn i18n">Insert</button>
|
||||
`;
|
||||
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 style="display: none">(.*?)<\/latex>/g, '\\($1\\)');
|
||||
htmlContent = htmlContent.replace(/<latex style="display: inline">(.*?)<\/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 = `
|
||||
<div style="display: flex; align-items: center; gap: 6px;">
|
||||
<span style="font-size: 14px;">⚠️</span>
|
||||
<span>${window.Asc.plugin.tr('Note: Some advanced LaTeX syntax may not be compatible with Document Editor. Manual adjustment might be needed.')}</span>
|
||||
</div>`;
|
||||
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 = '<h2 class="i18n">Results</h2>';
|
||||
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 => `<option value="${checkbox.value}">${checkbox.value.charAt(0).toUpperCase() + checkbox.value.slice(1)}</option>`)
|
||||
.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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
||||
22
sdkjs-plugins/content/mathpix/translations/de-DE.json
Normal file
@ -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."
|
||||
}
|
||||
22
sdkjs-plugins/content/mathpix/translations/es-ES.json
Normal file
@ -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."
|
||||
}
|
||||
22
sdkjs-plugins/content/mathpix/translations/fr-FR.json
Normal file
@ -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."
|
||||
}
|
||||
8
sdkjs-plugins/content/mathpix/translations/langs.json
Normal file
@ -0,0 +1,8 @@
|
||||
[
|
||||
"ru-RU",
|
||||
"de-DE",
|
||||
"fr-FR",
|
||||
"es-ES",
|
||||
"pt-BR",
|
||||
"zh-CN"
|
||||
]
|
||||
22
sdkjs-plugins/content/mathpix/translations/pt-BR.json
Normal file
@ -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."
|
||||
}
|
||||
22
sdkjs-plugins/content/mathpix/translations/ru-RU.json
Normal file
@ -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 могут быть несовместимы с Редактором документов. Может потребоваться ручная настройка."
|
||||
}
|
||||
22
sdkjs-plugins/content/mathpix/translations/zh-CN.json
Normal file
@ -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 语法可能与文档编辑器不兼容。可能需要手动调整。"
|
||||
}
|
||||
@ -224,6 +224,7 @@
|
||||
<option data-lang="en-GB" data-name="Google UK English Female">Google UK English Female (en-GB)</option>
|
||||
<option data-lang="en-GB" data-name="Google UK English Male">Google UK English Male (en-GB)</option>
|
||||
<option data-lang="en-US" data-name="Google US English">Google US English (en-US)</option>
|
||||
<option data-lang="uk-UA" data-name="Google українською">Google українською (uk-UA)</option>
|
||||
<option data-lang="ru-RU" data-name="Google русский">Google русский (ru-RU)</option>
|
||||
<option data-lang="hi-IN" data-name="Google हिन्दी">Google हिन्दी (hi-IN)</option>
|
||||
<option data-lang="zh-TW" data-name="Google 國語(臺灣)">Google 國語(臺灣) (zh-TW)</option>
|
||||
@ -248,4 +249,4 @@
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@ -1,28 +1,28 @@
|
||||
{
|
||||
"To use Zotero you should get an API key.": "如需使用 Zotero,您应该获取 API Key。",
|
||||
"Navigate to": "导航到",
|
||||
"Zotero API settings": "Zotero API 设置",
|
||||
"Create and copy API key into the field below.": "创建 API Key 并将其复制到下面的字段中。",
|
||||
"Open Zotero website": "Zotero 网站",
|
||||
"To use Zotero you should get an API key.": "使用 Zotero 插件前,请先获取 API Key。",
|
||||
"Navigate to": "访问",
|
||||
"Zotero API settings": "Zotero API 设置(需登录)",
|
||||
"Create and copy API key into the field below.": "创建 API Key 并贴至下方字段。",
|
||||
"Open Zotero website": "打开 Zotero 网站",
|
||||
"Invalid API key": "无效的 API Key",
|
||||
"API Key": "API Key",
|
||||
"Nothing found": "未找到任何内容",
|
||||
"Nothing found": "未找到任何文献",
|
||||
"Style is not selected": "未选择样式",
|
||||
"Language is not selected": "未选择语言",
|
||||
"Search references by author, title or year": "作者、标题或年份搜索引用",
|
||||
"Search references by author, title or year": "按作者、标题或年份搜索参考文献",
|
||||
"Cancel": "取消",
|
||||
"Insert Bibliography": "插入参考文献",
|
||||
"Insert Bibliography": "插入参考文献列表",
|
||||
"Style": "样式",
|
||||
"Enter style name": "输入样式名称",
|
||||
"Language": "语言",
|
||||
"Reconfigure": "重新配置",
|
||||
"Learn more here.": "在此处了解更多信息。",
|
||||
"Reconfigure": "重新配置插件",
|
||||
"Learn more here.": "点击此处了解更多信息。",
|
||||
"Save": "保存",
|
||||
"Insert Citation": "引用を挿入",
|
||||
"Cancel select": "キャンセル選択",
|
||||
"Refresh": "リフレッシュ",
|
||||
"Save as text": "テキストとして保存",
|
||||
"Please insert some citation into the document." : "文書にいくつかの引用を挿入してください。",
|
||||
"Synchronize" : "同期",
|
||||
"Omit Author" : "著者を省略する"
|
||||
"Insert Citation": "插入引用",
|
||||
"Cancel select": "取消选择",
|
||||
"Refresh": "刷新",
|
||||
"Save as text": "保存为文本",
|
||||
"Please insert some citation into the document." : "请插入一些引用到文档中。",
|
||||
"Synchronize" : "同步云端文献库",
|
||||
"Omit Author" : "同步"
|
||||
}
|
||||
@ -35,5 +35,6 @@
|
||||
{ "name": "onlydraw", "discussion": "" },
|
||||
{ "name": "pomodoro", "discussion": "" },
|
||||
{ "name": "videoembedder", "discussion": "" },
|
||||
{ "name": "mathtype", "discussion": "" }
|
||||
{ "name": "mathtype", "discussion": "" },
|
||||
{ "name": "mathpix", "discussion": "" }
|
||||
]
|
||||
|
||||