3838 <!-- Open Graph Image -->
3939 < meta property ="og:image " content ="https://sandikodev.github.io/snapcode/static/brand.png ">
4040
41- <!-- Fira Code Font -->
41+ <!-- DNS Prefetch & Preconnect for CDN -->
42+ < link rel ="dns-prefetch " href ="https://cdn.jsdelivr.net ">
43+ < link rel ="preconnect " href ="https://cdn.jsdelivr.net " crossorigin >
44+ < link rel ="dns-prefetch " href ="https://fonts.googleapis.com ">
45+ < link rel ="dns-prefetch " href ="https://fonts.gstatic.com ">
46+
47+ <!-- Fira Code Font with font-display swap -->
4248 < link rel ="preconnect " href ="https://fonts.googleapis.com ">
4349 < link rel ="preconnect " href ="https://fonts.gstatic.com " crossorigin >
4450 < link href ="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&display=swap " rel ="stylesheet ">
4551
46- <!-- KaTeX for Math -->
47- < link rel ="stylesheet " href ="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css ">
48- < script src ="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js "> </ script >
49- < script src ="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js "> </ script >
52+ <!-- KaTeX - Lazy loaded when enabled -->
53+ <!-- Moved to dynamic loading in script -->
5054
5155 <!-- Inline Prism CSS to avoid CORS -->
5256 < style >
200204 }
201205 </ style >
202206
203- < script src ="https://cdn.tailwindcss.com "> </ script >
204- < script src ="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js "> </ script >
205- < script src ="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-javascript.min.js "> </ script >
206- < script src ="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-python.min.js "> </ script >
207- < script src ="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-markup.min.js "> </ script >
208- < script src ="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-css.min.js "> </ script >
209- < script src ="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-java.min.js "> </ script >
210- < script src ="https://cdn.jsdelivr.net/npm/marked@11.1.1/marked.min.js "> </ script >
211- < script src ="https://cdn.jsdelivr.net/npm/dompurify@3.0.8/dist/purify.min.js "> </ script >
212- < script src ="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js "> </ script >
213- < script src ="https://cdn.jsdelivr.net/npm/mermaid@10.6.1/dist/mermaid.min.js "> </ script >
207+ <!-- Preload critical scripts -->
208+ < link rel ="preload " href ="https://cdn.jsdelivr.net/npm/alpinejs@3.13.3/dist/cdn.min.js " as ="script ">
209+ < link rel ="preload " href ="https://cdn.jsdelivr.net/npm/marked@11.1.1/marked.min.js " as ="script ">
210+
211+ <!-- Critical scripts (defer for non-blocking) -->
212+ < script defer src ="https://cdn.tailwindcss.com "> </ script >
213+ < script defer src ="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js "> </ script >
214+ < script defer src ="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-javascript.min.js "> </ script >
215+ < script defer src ="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-python.min.js "> </ script >
216+ < script defer src ="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-markup.min.js "> </ script >
217+ < script defer src ="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-css.min.js "> </ script >
218+ < script defer src ="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-java.min.js "> </ script >
219+ < script defer src ="https://cdn.jsdelivr.net/npm/marked@11.1.1/marked.min.js "> </ script >
220+ < script defer src ="https://cdn.jsdelivr.net/npm/dompurify@3.0.8/dist/purify.min.js "> </ script >
221+ < script defer src ="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js "> </ script >
222+
223+ <!-- Heavy dependencies - Lazy loaded when needed -->
224+ <!-- Mermaid & KaTeX loaded dynamically -->
225+
214226 < script defer src ="https://cdn.jsdelivr.net/npm/alpinejs@3.13.3/dist/cdn.min.js "> </ script >
215227
216228 < style >
@@ -754,6 +766,64 @@ <h2 class="text-xl font-semibold text-white">Preview</h2>
754766 </ div >
755767
756768 < script >
769+ // Lazy Loading Utilities
770+ const loadedScripts = new Set ( ) ;
771+ const loadedStyles = new Set ( ) ;
772+
773+ function loadScript ( src ) {
774+ if ( loadedScripts . has ( src ) ) return Promise . resolve ( ) ;
775+
776+ return new Promise ( ( resolve , reject ) => {
777+ const script = document . createElement ( 'script' ) ;
778+ script . src = src ;
779+ script . onload = ( ) => {
780+ loadedScripts . add ( src ) ;
781+ resolve ( ) ;
782+ } ;
783+ script . onerror = reject ;
784+ document . head . appendChild ( script ) ;
785+ } ) ;
786+ }
787+
788+ function loadStyle ( href ) {
789+ if ( loadedStyles . has ( href ) ) return Promise . resolve ( ) ;
790+
791+ return new Promise ( ( resolve , reject ) => {
792+ const link = document . createElement ( 'link' ) ;
793+ link . rel = 'stylesheet' ;
794+ link . href = href ;
795+ link . onload = ( ) => {
796+ loadedStyles . add ( href ) ;
797+ resolve ( ) ;
798+ } ;
799+ link . onerror = reject ;
800+ document . head . appendChild ( link ) ;
801+ } ) ;
802+ }
803+
804+ // Lazy load KaTeX
805+ async function loadKaTeX ( ) {
806+ if ( window . katex ) return ;
807+
808+ await Promise . all ( [
809+ loadStyle ( 'https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css' ) ,
810+ loadScript ( 'https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js' )
811+ ] ) ;
812+
813+ await loadScript ( 'https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js' ) ;
814+ }
815+
816+ // Lazy load Mermaid
817+ async function loadMermaid ( ) {
818+ if ( window . mermaid ) return ;
819+
820+ await loadScript ( 'https://cdn.jsdelivr.net/npm/mermaid@10.6.1/dist/mermaid.min.js' ) ;
821+
822+ if ( window . mermaid ) {
823+ mermaid . initialize ( { startOnLoad : false , theme : 'dark' } ) ;
824+ }
825+ }
826+
757827 function app ( ) {
758828 return {
759829 content : '' ,
@@ -883,8 +953,16 @@ <h2 class="text-xl font-semibold text-white">Preview</h2>
883953 const raw = marked . parse ( this . content ) ;
884954 let html = DOMPurify . sanitize ( raw ) ;
885955
886- // Process Mermaid diagrams if enabled
887- if ( this . useMermaid ) {
956+ // Lazy load and process Mermaid diagrams if enabled
957+ if ( this . useMermaid && html . includes ( 'language-mermaid' ) ) {
958+ loadMermaid ( ) . then ( ( ) => {
959+ this . $nextTick ( ( ) => {
960+ if ( window . mermaid ) {
961+ mermaid . run ( ) ;
962+ }
963+ } ) ;
964+ } ) ;
965+
888966 html = html . replace ( / < p r e > < c o d e c l a s s = " l a n g u a g e - m e r m a i d " > ( [ \s \S ] * ?) < \/ c o d e > < \/ p r e > / g, ( match , code ) => {
889967 const decoded = code
890968 . replace ( / & l t ; / g, '<' )
@@ -896,6 +974,27 @@ <h2 class="text-xl font-semibold text-white">Preview</h2>
896974 } ) ;
897975 }
898976
977+ // Lazy load KaTeX if math detected
978+ if ( this . useKatex && ( html . includes ( '$' ) || html . includes ( '\\(' ) ) ) {
979+ loadKaTeX ( ) . then ( ( ) => {
980+ this . $nextTick ( ( ) => {
981+ if ( window . renderMathInElement ) {
982+ const element = document . querySelector ( '.preview-content' ) ;
983+ if ( element ) {
984+ renderMathInElement ( element , {
985+ delimiters : [
986+ { left : '$$' , right : '$$' , display : true } ,
987+ { left : '$' , right : '$' , display : false } ,
988+ { left : '\\(' , right : '\\)' , display : false } ,
989+ { left : '\\[' , right : '\\]' , display : true }
990+ ]
991+ } ) ;
992+ }
993+ }
994+ } ) ;
995+ } ) ;
996+ }
997+
899998 return html ;
900999 } ,
9011000
0 commit comments