Skip to content

Commit 7aeb59a

Browse files
build: compile and synchronize performance updates into desktop application resources
1 parent 6fc0dbd commit 7aeb59a

2 files changed

Lines changed: 73 additions & 28 deletions

File tree

desktop-app/resources/index.html

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<!-- DNS Prefetch & Preconnect CDN Origins to Warm Up Latency -->
7+
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
8+
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
9+
<link rel="dns-prefetch" href="https://cdnjs.cloudflare.com">
10+
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net">
11+
612
<!-- Primary Meta Tags -->
713
<meta name="title" content="Markdown Viewer">
814
<meta name="description" content="Markdown Viewer is a powerful GitHub-style Markdown rendering tool with live preview, LaTeX math, Mermaid diagrams, syntax highlighting, dark mode, and export options to PDF, HTML, and MD—all fully client-side and secure.">
@@ -36,12 +42,11 @@
3642
<link rel="stylesheet" href="/libs/joypixels.min.css" integrity="sha384-4ok+tBQQdy5hcPT56tzcE11yQ2BkN0Py1uDE8ZOiXYstHOpUB61pJafm+NidByp4" crossorigin="anonymous">
3743
<link rel="stylesheet" href="/styles.css">
3844

39-
<!-- Loading order optimized - ensure libraries are loaded before they're used -->
40-
<script src="/libs/marked.min.js" integrity="sha384-odPBjvtXVM/5hOYIr3A1dB+flh0c3wAT3bSesIOqEGmyUA4JoKf/YTWy0XKOYAY7" crossorigin="anonymous"></script>
41-
<script src="/libs/highlight.min.js" integrity="sha384-F/bZzf7p3Joyp5psL90p/p89AZJsndkSoGwRpXcZhleCWhd8SnRuoYo4d0yirjJp" crossorigin="anonymous"></script>
42-
<script src="/libs/purify.min.js" integrity="sha384-3HPB1XT51W3gGRxAmZ+qbZwRpRlFQL632y8x+adAqCr4Wp3TaWwCLSTAJJKbyWEK" crossorigin="anonymous"></script>
43-
<script src="/libs/FileSaver.min.js" integrity="sha384-PlRSzpewlarQuj5alIadXwjNUX+2eNMKwr0f07ShWYLy8B6TjEbm7ZlcN/ScSbwy" crossorigin="anonymous"></script>
44-
<script src="/libs/html2pdf.bundle.min.js" integrity="sha384-Yv5O+t3uE3hunW8uyrbpPW3iw6/5/Y7HitWJBLgqfMoA36NogMmy+8wWZMpn3HWc" crossorigin="anonymous"></script>
45+
<!-- Loading order optimized - ensure libraries are loaded asynchronously using defer -->
46+
<script src="/libs/marked.min.js" integrity="sha384-odPBjvtXVM/5hOYIr3A1dB+flh0c3wAT3bSesIOqEGmyUA4JoKf/YTWy0XKOYAY7" crossorigin="anonymous" defer></script>
47+
<script src="/libs/highlight.min.js" integrity="sha384-F/bZzf7p3Joyp5psL90p/p89AZJsndkSoGwRpXcZhleCWhd8SnRuoYo4d0yirjJp" crossorigin="anonymous" defer></script>
48+
<script src="/libs/purify.min.js" integrity="sha384-3HPB1XT51W3gGRxAmZ+qbZwRpRlFQL632y8x+adAqCr4Wp3TaWwCLSTAJJKbyWEK" crossorigin="anonymous" defer></script>
49+
<script src="/libs/FileSaver.min.js" integrity="sha384-PlRSzpewlarQuj5alIadXwjNUX+2eNMKwr0f07ShWYLy8B6TjEbm7ZlcN/ScSbwy" crossorigin="anonymous" defer></script>
4550
<script>
4651
window.MathJax = {
4752
loader: { load: ['[tex]/ams', '[tex]/boldsymbol'] },
@@ -53,16 +58,13 @@
5358
}
5459
};
5560
</script>
56-
<script src="/libs/tex-mml-chtml.min.js" integrity="sha384-M5jmNxKC9EVnuqeMwRHvFuYUE8Hhp0TgBruj/GZRkYtiMrCRgH7yvv5KY+Owi7TW" crossorigin="anonymous"></script>
57-
<script src="/libs/mermaid.min.js" integrity="sha384-zkWMJO4sgpPUzyuOgDx8HB/K55glbAwajEpk1Go2NWRuPkPA/wIhoEJTuSkmOYrV" crossorigin="anonymous"></script>
58-
<script src="/libs/joypixels.min.js" integrity="sha384-1+n1eMmP5I08CibRJ6JmycJ0hP3G6C0fuUtTb4bEuQgl9uFdS9pnPePfpmrXl9ll" crossorigin="anonymous"></script>
59-
<script src="/libs/jspdf.umd.min.js" integrity="sha384-JcnsjUPPylna1s1fvi1u12X5qjY5OL56iySh75FdtrwhO/SWXgMjoVqcKyIIWOLk" crossorigin="anonymous"></script>
60-
<script src="/libs/html2canvas.min.js" integrity="sha384-ZZ1pncU3bQe8y31yfZdMFdSpttDoPmOZg2wguVK9almUodir1PghgT0eY7Mrty8H" crossorigin="anonymous"></script>
61-
62-
<script src="/libs/pdfmake.min.js" integrity="sha384-VFQrHzqBh5qiJIU0uGU5CIW3+OWpdGGJM9LBnGbuIH2mkICcFZ7lPd/AAtI7SNf7" crossorigin="anonymous"></script>
63-
<script src="/libs/vfs_fonts.js" integrity="sha384-/RlQG9uf0M2vcTw3CX7fbqgbj/h8wKxw7C3zu9/GxcBPRKOEcESxaxufwRXqzq6n" crossorigin="anonymous"></script>
64-
<script src="/libs/pako.min.js" integrity="sha384-rNlaE5fs9dGIjmxWDALQh/RBAaGRYT5ChrzHo6tRfgrZ36iRFAiquP5g41Jsv+0j" crossorigin="anonymous"></script>
65-
<script src="/libs/js-yaml.min.js" integrity="sha384-+pxiN6T7yvpryuJmE1gM9PX7yQit15auDb+ZwwvJOd/4be2Cie5/IuVXgQb/S9du" crossorigin="anonymous"></script>
61+
<script src="/libs/tex-mml-chtml.min.js" integrity="sha384-M5jmNxKC9EVnuqeMwRHvFuYUE8Hhp0TgBruj/GZRkYtiMrCRgH7yvv5KY+Owi7TW" crossorigin="anonymous" defer></script>
62+
<script src="/libs/mermaid.min.js" integrity="sha384-zkWMJO4sgpPUzyuOgDx8HB/K55glbAwajEpk1Go2NWRuPkPA/wIhoEJTuSkmOYrV" crossorigin="anonymous" defer></script>
63+
<script src="/libs/joypixels.min.js" integrity="sha384-1+n1eMmP5I08CibRJ6JmycJ0hP3G6C0fuUtTb4bEuQgl9uFdS9pnPePfpmrXl9ll" crossorigin="anonymous" defer></script>
64+
<script src="/libs/jspdf.umd.min.js" integrity="sha384-JcnsjUPPylna1s1fvi1u12X5qjY5OL56iySh75FdtrwhO/SWXgMjoVqcKyIIWOLk" crossorigin="anonymous" defer></script>
65+
<script src="/libs/html2canvas.min.js" integrity="sha384-ZZ1pncU3bQe8y31yfZdMFdSpttDoPmOZg2wguVK9almUodir1PghgT0eY7Mrty8H" crossorigin="anonymous" defer></script>
66+
<script src="/libs/pako.min.js" integrity="sha384-rNlaE5fs9dGIjmxWDALQh/RBAaGRYT5ChrzHo6tRfgrZ36iRFAiquP5g41Jsv+0j" crossorigin="anonymous" defer></script>
67+
<script src="/libs/js-yaml.min.js" integrity="sha384-+pxiN6T7yvpryuJmE1gM9PX7yQit15auDb+ZwwvJOd/4be2Cie5/IuVXgQb/S9du" crossorigin="anonymous" defer></script>
6668
</head>
6769
<body>
6870
<div class="app-container">

desktop-app/resources/js/script.js

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ document.addEventListener("DOMContentLoaded", function () {
99

1010
// View Mode State - Story 1.1
1111
let currentViewMode = 'split'; // 'editor', 'split', or 'preview'
12-
const APP_VERSION = '3.6.1';
12+
const APP_VERSION = '3.6.2';
1313
let activeModal = null;
1414
let lastFocusedElement = null;
1515
let isFindModalOpen = false;
@@ -3631,36 +3631,68 @@ This is a fully client-side application. Your content never leaves your browser
36313631
return Math.max(1, Math.round(contentHeight / lineHeight));
36323632
}
36333633

3634+
const lineCache = new Map();
3635+
let lastEditorWidth = 0;
3636+
36343637
function updateLineNumbers() {
36353638
if (!lineNumbers || !markdownEditor) return;
36363639
const lines = (markdownEditor.value || '').split('\n');
36373640
const lineCount = Math.max(1, lines.length);
3641+
3642+
// Clear height cache if editor width has changed
3643+
const currentWidth = markdownEditor.clientWidth;
3644+
if (currentWidth !== lastEditorWidth) {
3645+
lineCache.clear();
3646+
lastEditorWidth = currentWidth;
3647+
}
3648+
36383649
updateLineNumberGutter(lineCount);
36393650
ensureLineNumberMeasure();
36403651
const styles = window.getComputedStyle(markdownEditor);
36413652
const lineHeight = getLineHeight(styles);
36423653
const paddingSum =
36433654
(parseFloat(styles.paddingTop) || 0) +
36443655
(parseFloat(styles.paddingBottom) || 0);
3656+
36453657
const existingItems = lineNumbers.children;
3646-
if (existingItems.length !== lineCount) {
3658+
const existingCount = existingItems.length;
3659+
3660+
// Adjust the number of DOM elements in-place to avoid complete tear-down
3661+
if (existingCount < lineCount) {
36473662
const fragment = document.createDocumentFragment();
3648-
lines.forEach(function(line, index) {
3663+
for (let i = existingCount; i < lineCount; i += 1) {
36493664
const lineNumber = document.createElement('div');
36503665
lineNumber.className = 'line-number';
3651-
lineNumber.textContent = index + 1;
3652-
const wrapCount = getWrappedLineCount(line, lineHeight, paddingSum);
3653-
lineNumber.style.height = `${wrapCount * lineHeight}px`;
36543666
fragment.appendChild(lineNumber);
3655-
});
3656-
lineNumbers.textContent = '';
3667+
}
36573668
lineNumbers.appendChild(fragment);
3658-
} else {
3659-
for (let i = 0; i < lineCount; i += 1) {
3660-
const wrapCount = getWrappedLineCount(lines[i], lineHeight, paddingSum);
3661-
existingItems[i].style.height = `${wrapCount * lineHeight}px`;
3669+
} else if (existingCount > lineCount) {
3670+
while (lineNumbers.children.length > lineCount) {
3671+
lineNumbers.removeChild(lineNumbers.lastChild);
3672+
}
3673+
}
3674+
3675+
// Update only the heights and numbers that changed, querying cache
3676+
for (let i = 0; i < lineCount; i += 1) {
3677+
const lineText = lines[i];
3678+
let wrapHeight = lineCache.get(lineText);
3679+
if (wrapHeight === undefined) {
3680+
const wrapCount = getWrappedLineCount(lineText, lineHeight, paddingSum);
3681+
wrapHeight = wrapCount * lineHeight;
3682+
lineCache.set(lineText, wrapHeight);
3683+
}
3684+
3685+
const item = existingItems[i];
3686+
const targetText = String(i + 1);
3687+
if (item.textContent !== targetText) {
3688+
item.textContent = targetText;
3689+
}
3690+
const targetHeight = `${wrapHeight}px`;
3691+
if (item.style.height !== targetHeight) {
3692+
item.style.height = targetHeight;
36623693
}
36633694
}
3695+
36643696
syncLineNumberScroll();
36653697
}
36663698

@@ -5868,4 +5900,15 @@ This is a fully client-side application. Your content never leaves your browser
58685900
container.appendChild(toolbar);
58695901
});
58705902
}
5903+
5904+
// Register Service Worker for offline capabilities
5905+
if ('serviceWorker' in navigator) {
5906+
window.addEventListener('load', function() {
5907+
navigator.serviceWorker.register('sw.js').then(function(registration) {
5908+
console.log('ServiceWorker registration successful with scope: ', registration.scope);
5909+
}, function(err) {
5910+
console.log('ServiceWorker registration failed: ', err);
5911+
});
5912+
});
5913+
}
58715914
});

0 commit comments

Comments
 (0)