Commit ·
5bb4bf0
1
Parent(s): cd72e8b
feat: apply includes surah ref + quran-applied span protects from analysis models
Browse files- src/css/components.css +19 -0
- src/index.html +20 -8
- src/js/renderer.js +6 -1
src/css/components.css
CHANGED
|
@@ -3065,6 +3065,25 @@ input[type="range"]::-moz-range-thumb {
|
|
| 3065 |
}
|
| 3066 |
.quran-modal.is-hidden { display: none; }
|
| 3067 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3068 |
.quran-modal-backdrop {
|
| 3069 |
position: absolute;
|
| 3070 |
inset: 0;
|
|
|
|
| 3065 |
}
|
| 3066 |
.quran-modal.is-hidden { display: none; }
|
| 3067 |
|
| 3068 |
+
/* Quran applied text — protected from analysis */
|
| 3069 |
+
.quran-applied {
|
| 3070 |
+
display: inline;
|
| 3071 |
+
background: rgba(6, 182, 212, 0.1);
|
| 3072 |
+
border-bottom: 2px solid rgba(6, 182, 212, 0.4);
|
| 3073 |
+
border-radius: 4px;
|
| 3074 |
+
padding: 1px 4px;
|
| 3075 |
+
cursor: default;
|
| 3076 |
+
user-select: text;
|
| 3077 |
+
}
|
| 3078 |
+
.quran-applied .spelling-error,
|
| 3079 |
+
.quran-applied .grammar-error,
|
| 3080 |
+
.quran-applied .punctuation-suggestion {
|
| 3081 |
+
text-decoration: none !important;
|
| 3082 |
+
border-bottom: none !important;
|
| 3083 |
+
background: none !important;
|
| 3084 |
+
cursor: default !important;
|
| 3085 |
+
}
|
| 3086 |
+
|
| 3087 |
.quran-modal-backdrop {
|
| 3088 |
position: absolute;
|
| 3089 |
inset: 0;
|
src/index.html
CHANGED
|
@@ -1202,6 +1202,8 @@
|
|
| 1202 |
let _quranSavedRange = null;
|
| 1203 |
let _quranVerseClean = '';
|
| 1204 |
let _quranTransClean = '';
|
|
|
|
|
|
|
| 1205 |
|
| 1206 |
async function verifyQuranText() {
|
| 1207 |
const sel = window.getSelection();
|
|
@@ -1246,6 +1248,7 @@
|
|
| 1246 |
const reference = refMatch ? refMatch[1] : '';
|
| 1247 |
|
| 1248 |
_quranVerseClean = verseText;
|
|
|
|
| 1249 |
document.getElementById('quran-uthmani-text').textContent = verseText;
|
| 1250 |
document.getElementById('quran-reference').textContent = reference ? '[' + reference + ']' : '';
|
| 1251 |
// Show apply button
|
|
@@ -1287,6 +1290,7 @@
|
|
| 1287 |
|
| 1288 |
textEl.textContent = transText;
|
| 1289 |
_quranTransClean = transText;
|
|
|
|
| 1290 |
// Show reference in translated language
|
| 1291 |
const refEl = document.getElementById('quran-translation-ref');
|
| 1292 |
if (refEl) {
|
|
@@ -1306,16 +1310,24 @@
|
|
| 1306 |
document.body.style.overflow = '';
|
| 1307 |
}
|
| 1308 |
|
| 1309 |
-
function _replaceInEditor(newText) {
|
| 1310 |
var editor = document.getElementById('editor-container');
|
| 1311 |
if (!editor || !_quranCurrentQuery) return false;
|
| 1312 |
closeQuranModal();
|
| 1313 |
-
//
|
|
|
|
|
|
|
|
|
|
| 1314 |
var plain = editor.textContent || '';
|
| 1315 |
-
|
| 1316 |
-
|
| 1317 |
-
var
|
| 1318 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1319 |
editor.focus();
|
| 1320 |
editor.dispatchEvent(new Event('input', { bubbles: true }));
|
| 1321 |
return true;
|
|
@@ -1326,7 +1338,7 @@
|
|
| 1326 |
if (typeof showToast === 'function') showToast('لا يوجد نص للتطبيق');
|
| 1327 |
return;
|
| 1328 |
}
|
| 1329 |
-
if (_replaceInEditor(_quranVerseClean)) {
|
| 1330 |
if (typeof showToast === 'function') showToast('✓ تم تطبيق النص القرآني المدقق');
|
| 1331 |
} else {
|
| 1332 |
if (typeof showToast === 'function') showToast('لم يتم العثور على النص الأصلي');
|
|
@@ -1338,7 +1350,7 @@
|
|
| 1338 |
if (typeof showToast === 'function') showToast('لا يوجد ترجمة للتطبيق');
|
| 1339 |
return;
|
| 1340 |
}
|
| 1341 |
-
if (_replaceInEditor(_quranTransClean)) {
|
| 1342 |
if (typeof showToast === 'function') showToast('✓ تم تطبيق الترجمة');
|
| 1343 |
} else {
|
| 1344 |
if (typeof showToast === 'function') showToast('لم يتم العثور على النص الأصلي');
|
|
|
|
| 1202 |
let _quranSavedRange = null;
|
| 1203 |
let _quranVerseClean = '';
|
| 1204 |
let _quranTransClean = '';
|
| 1205 |
+
let _quranRef = '';
|
| 1206 |
+
let _quranTransRef = '';
|
| 1207 |
|
| 1208 |
async function verifyQuranText() {
|
| 1209 |
const sel = window.getSelection();
|
|
|
|
| 1248 |
const reference = refMatch ? refMatch[1] : '';
|
| 1249 |
|
| 1250 |
_quranVerseClean = verseText;
|
| 1251 |
+
_quranRef = reference;
|
| 1252 |
document.getElementById('quran-uthmani-text').textContent = verseText;
|
| 1253 |
document.getElementById('quran-reference').textContent = reference ? '[' + reference + ']' : '';
|
| 1254 |
// Show apply button
|
|
|
|
| 1290 |
|
| 1291 |
textEl.textContent = transText;
|
| 1292 |
_quranTransClean = transText;
|
| 1293 |
+
_quranTransRef = transRef;
|
| 1294 |
// Show reference in translated language
|
| 1295 |
const refEl = document.getElementById('quran-translation-ref');
|
| 1296 |
if (refEl) {
|
|
|
|
| 1310 |
document.body.style.overflow = '';
|
| 1311 |
}
|
| 1312 |
|
| 1313 |
+
function _replaceInEditor(newText, ref) {
|
| 1314 |
var editor = document.getElementById('editor-container');
|
| 1315 |
if (!editor || !_quranCurrentQuery) return false;
|
| 1316 |
closeQuranModal();
|
| 1317 |
+
// Build the full text with reference
|
| 1318 |
+
var fullText = newText;
|
| 1319 |
+
if (ref) fullText += ' [' + ref + ']';
|
| 1320 |
+
// Replace in editor: wrap in quran-applied span to protect from analysis
|
| 1321 |
var plain = editor.textContent || '';
|
| 1322 |
+
var idx = plain.indexOf(_quranCurrentQuery);
|
| 1323 |
+
if (idx === -1) return false;
|
| 1324 |
+
var before = plain.substring(0, idx);
|
| 1325 |
+
var after = plain.substring(idx + _quranCurrentQuery.length);
|
| 1326 |
+
// Build HTML: before (escaped) + quran span + after (escaped)
|
| 1327 |
+
var esc = function(t) { return t.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); };
|
| 1328 |
+
editor.innerHTML = esc(before) +
|
| 1329 |
+
'<span class="quran-applied" contenteditable="false" data-quran="true">' + esc(fullText) + '</span>' +
|
| 1330 |
+
esc(after);
|
| 1331 |
editor.focus();
|
| 1332 |
editor.dispatchEvent(new Event('input', { bubbles: true }));
|
| 1333 |
return true;
|
|
|
|
| 1338 |
if (typeof showToast === 'function') showToast('لا يوجد نص للتطبيق');
|
| 1339 |
return;
|
| 1340 |
}
|
| 1341 |
+
if (_replaceInEditor(_quranVerseClean, _quranRef)) {
|
| 1342 |
if (typeof showToast === 'function') showToast('✓ تم تطبيق النص القرآني المدقق');
|
| 1343 |
} else {
|
| 1344 |
if (typeof showToast === 'function') showToast('لم يتم العثور على النص الأصلي');
|
|
|
|
| 1350 |
if (typeof showToast === 'function') showToast('لا يوجد ترجمة للتطبيق');
|
| 1351 |
return;
|
| 1352 |
}
|
| 1353 |
+
if (_replaceInEditor(_quranTransClean, _quranTransRef)) {
|
| 1354 |
if (typeof showToast === 'function') showToast('✓ تم تطبيق الترجمة');
|
| 1355 |
} else {
|
| 1356 |
if (typeof showToast === 'function') showToast('لم يتم العثور على النص الأصلي');
|
src/js/renderer.js
CHANGED
|
@@ -243,10 +243,15 @@ function overlaySuggestions(editor, suggestions) {
|
|
| 243 |
|
| 244 |
if (!suggestions || suggestions.length === 0) return;
|
| 245 |
|
| 246 |
-
// 2. Collect text nodes with their character offsets
|
| 247 |
const textNodes = [];
|
| 248 |
let offset = 0;
|
| 249 |
walkTextNodes(editor, (node) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 250 |
textNodes.push({ node, start: offset, end: offset + node.length });
|
| 251 |
offset += node.length;
|
| 252 |
});
|
|
|
|
| 243 |
|
| 244 |
if (!suggestions || suggestions.length === 0) return;
|
| 245 |
|
| 246 |
+
// 2. Collect text nodes with their character offsets (skip quran-applied)
|
| 247 |
const textNodes = [];
|
| 248 |
let offset = 0;
|
| 249 |
walkTextNodes(editor, (node) => {
|
| 250 |
+
// Skip text inside quran-applied spans (protected from analysis)
|
| 251 |
+
if (node.parentElement && node.parentElement.closest('.quran-applied')) {
|
| 252 |
+
offset += node.length; // still count offset to keep positions correct
|
| 253 |
+
return;
|
| 254 |
+
}
|
| 255 |
textNodes.push({ node, start: offset, end: offset + node.length });
|
| 256 |
offset += node.length;
|
| 257 |
});
|