index.html 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <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. <!-- PERF-015: Preload critical-path resources for faster discovery -->
  12. <link rel="preload" href="styles.css" as="style">
  13. <link rel="preload" href="script.js" as="script">
  14. <!-- Canonical Link -->
  15. <link rel="canonical" href="https://markdownplusplus.pages.dev/">
  16. <!-- Multilingual Hreflang Tags for Search Crawlers -->
  17. <link rel="alternate" hreflang="x-default" href="https://markdownplusplus.pages.dev/" />
  18. <link rel="alternate" hreflang="en" href="https://markdownplusplus.pages.dev/?lang=en" />
  19. <link rel="alternate" hreflang="zh-Hans" href="https://markdownplusplus.pages.dev/?lang=zh" />
  20. <link rel="alternate" hreflang="ja" href="https://markdownplusplus.pages.dev/?lang=ja" />
  21. <link rel="alternate" hreflang="ko" href="https://markdownplusplus.pages.dev/?lang=ko" />
  22. <link rel="alternate" hreflang="pt-BR" href="https://markdownplusplus.pages.dev/?lang=pt" />
  23. <link rel="alternate" hreflang="es" href="https://markdownplusplus.pages.dev/?lang=es" />
  24. <link rel="alternate" hreflang="fr" href="https://markdownplusplus.pages.dev/?lang=fr" />
  25. <link rel="alternate" hreflang="de" href="https://markdownplusplus.pages.dev/?lang=de" />
  26. <link rel="alternate" hreflang="ru" href="https://markdownplusplus.pages.dev/?lang=ru" />
  27. <link rel="alternate" hreflang="it" href="https://markdownplusplus.pages.dev/?lang=it" />
  28. <link rel="alternate" hreflang="tr" href="https://markdownplusplus.pages.dev/?lang=tr" />
  29. <link rel="alternate" hreflang="pl" href="https://markdownplusplus.pages.dev/?lang=pl" />
  30. <link rel="alternate" hreflang="zh-Hant" href="https://markdownplusplus.pages.dev/?lang=tw" />
  31. <link rel="alternate" hreflang="uk" href="https://markdownplusplus.pages.dev/?lang=uk" />
  32. <!-- PWA Web Manifest -->
  33. <link rel="manifest" href="manifest.json">
  34. <!-- Primary Meta Tags -->
  35. <meta name="title" content="Markdown ++">
  36. <meta name="description" content="Markdown ++ 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.">
  37. <meta name="keywords" content="Markdown ++, GitHub-style markdown, live preview, markdown editor, LaTeX support, Mermaid diagrams, PDF export, syntax highlighting, markdown to HTML, secure markdown tool, client-side Markdown ++, Parv Ashwani, advanced markdown parser, future Markdown ++, next-gen markdown tool">
  38. <meta name="author" content="Parv Ashwani">
  39. <meta name="robots" content="index, follow">
  40. <meta name="language" content="English">
  41. <meta name="distribution" content="global">
  42. <meta name="rating" content="general">
  43. <!-- Open Graph / Facebook -->
  44. <meta property="og:type" content="website">
  45. <meta property="og:url" content="https://markdownplusplus.pages.dev/">
  46. <meta property="og:title" content="Markdown ++">
  47. <meta property="og:description" content="Markdown ++ 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.">
  48. <meta property="og:image" content="https://markdownplusplus.pages.dev/assets/icon.jpg">
  49. <!-- Twitter -->
  50. <meta property="twitter:card" content="summary_large_image">
  51. <meta property="twitter:url" content="https://markdownplusplus.pages.dev/">
  52. <meta property="twitter:title" content="Markdown ++">
  53. <meta property="twitter:description" content="Markdown ++ 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.">
  54. <meta property="twitter:image" content="https://markdownplusplus.pages.dev/assets/icon.jpg">
  55. <!-- JSON-LD Structured Data Schema for Search Rich Snippets -->
  56. <script type="application/ld+json">
  57. {
  58. "@context": "https://schema.org",
  59. "@type": "WebApplication",
  60. "name": "Markdown ++",
  61. "url": "https://markdownplusplus.pages.dev/",
  62. "image": "https://markdownplusplus.pages.dev/assets/icon.jpg",
  63. "description": "A powerful GitHub-style Markdown rendering tool with live preview, LaTeX, Mermaid, syntax highlighting, and PDF export.",
  64. "applicationCategory": "DeveloperApplication",
  65. "operatingSystem": "All",
  66. "browserRequirements": "Requires HTML5 compatible browser",
  67. "author": {
  68. "@type": "Organization",
  69. "name": "Parv Ashwani",
  70. "url": "https://github.com/Parv Ashwani"
  71. },
  72. "offers": {
  73. "@type": "Offer",
  74. "price": "0.00",
  75. "priceCurrency": "USD"
  76. }
  77. }
  78. </script>
  79. <title>Markdown ++</title>
  80. <link href="assets/icon.jpg" rel="icon" type="image/jpg">
  81. <!-- Updated libraries to latest versions with Subresource Integrity (SRI) -->
  82. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/css/bootstrap.min.css" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
  83. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.3.0/github-markdown.min.css" integrity="sha384-hZuxRjC/Dsr4zEx1JlUhDQqkvqBPp2VLHsgXfnxPq1ULDy1eIdWCiux7nvO1RIZP" crossorigin="anonymous">
  84. <link rel="preload" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" as="style" integrity="sha384-XGjxtQfXaH2tnPFa9x+ruJTuLE3Aa6LhHSWRr1XeTyhezb4abCG4ccI5AkVDxqC+" crossorigin="anonymous" onload="this.onload=null;this.rel='stylesheet'">
  85. <noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" integrity="sha384-XGjxtQfXaH2tnPFa9x+ruJTuLE3Aa6LhHSWRr1XeTyhezb4abCG4ccI5AkVDxqC+" crossorigin="anonymous"></noscript>
  86. <link rel="stylesheet" href="styles.css">
  87. <!-- Loading order optimized - ensure libraries are loaded asynchronously using defer -->
  88. <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.6/marked.min.js" integrity="sha384-odPBjvtXVM/5hOYIr3A1dB+flh0c3wAT3bSesIOqEGmyUA4JoKf/YTWy0XKOYAY7" crossorigin="anonymous" defer></script>
  89. <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha384-F/bZzf7p3Joyp5psL90p/p89AZJsndkSoGwRpXcZhleCWhd8SnRuoYo4d0yirjJp" crossorigin="anonymous" defer></script>
  90. <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.9/purify.min.js" integrity="sha384-3HPB1XT51W3gGRxAmZ+qbZwRpRlFQL632y8x+adAqCr4Wp3TaWwCLSTAJJKbyWEK" crossorigin="anonymous" defer></script>
  91. <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js" integrity="sha384-PlRSzpewlarQuj5alIadXwjNUX+2eNMKwr0f07ShWYLy8B6TjEbm7ZlcN/ScSbwy" crossorigin="anonymous" defer></script>
  92. <!-- PERF-002: MathJax, Mermaid, JoyPixels, jsPDF, html2canvas, pako are now lazy-loaded by script.js on first use -->
  93. <script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js" integrity="sha384-+pxiN6T7yvpryuJmE1gM9PX7yQit15auDb+ZwwvJOd/4be2Cie5/IuVXgQb/S9du" crossorigin="anonymous" defer></script>
  94. </head>
  95. <body>
  96. <div class="app-container">
  97. <header class="app-header">
  98. <div class="container-fluid d-flex justify-content-between align-items-center header-container">
  99. <!-- Left section: Logo, GitHub, Stats -->
  100. <div class="d-flex align-items-center header-left">
  101. <h1 class="h4 mb-0 me-2">Markdown ++</h1>
  102. <a href="https://git.4parv.in/parv.ashwani/markdownplusplus/" class="github-link" title="View on GitHub" target="_blank" rel="noopener noreferrer">
  103. <i class="bi bi-github"></i>
  104. </a>
  105. <div id="stats-container" class="stats-container d-flex align-items-center d-none d-md-flex">
  106. <div class="stat-item me-3">
  107. <i class="bi bi-clock me-1"></i> <span id="reading-time">0</span> <span id="lbl-min-read">Min Read</span>
  108. </div>
  109. <div class="stat-item me-3">
  110. <i class="bi bi-text-paragraph me-1"></i> <span id="word-count">0</span> <span id="lbl-words">Words</span>
  111. </div>
  112. <div class="stat-item">
  113. <i class="bi bi-fonts me-1"></i> <span id="char-count">0</span> <span id="lbl-chars">Chars</span>
  114. </div>
  115. </div>
  116. </div>
  117. <!-- Right section: Toolbar -->
  118. <div class="toolbar d-none d-md-flex header-right">
  119. <div class="toolbar-group view-toolbar" role="group" aria-label="View mode">
  120. <button class="tool-button view-toggle-btn" data-view-mode="editor" aria-pressed="false" title="Editor only" aria-label="Editor only">
  121. <i class="bi bi-file-text"></i>
  122. </button>
  123. <button class="tool-button view-toggle-btn is-active" data-view-mode="split" aria-pressed="true" title="Split view" aria-label="Split view">
  124. <i class="bi bi-layout-split"></i>
  125. </button>
  126. <button class="tool-button view-toggle-btn" data-view-mode="preview" aria-pressed="false" title="Preview only" aria-label="Preview only">
  127. <i class="bi bi-eye"></i>
  128. </button>
  129. </div>
  130. <span class="toolbar-divider" aria-hidden="true"></span>
  131. <button id="toggle-sync" class="tool-button sync-enabled sync-active" title="Toggle Sync Scrolling">
  132. <i class="bi bi-link"></i> <span class="btn-text">Sync Off</span>
  133. </button>
  134. <div class="dropdown">
  135. <button class="tool-button dropdown-toggle" type="button" id="importDropdown" data-bs-toggle="dropdown" aria-expanded="false" title="Import Markdown">
  136. <i class="bi bi-upload"></i> <span class="btn-text">Import</span>
  137. </button>
  138. <ul class="dropdown-menu" aria-labelledby="importDropdown">
  139. <li><a class="dropdown-item" href="#" id="import-from-file"><i class="bi bi-upload me-2"></i>From files</a></li>
  140. <li><a class="dropdown-item" href="#" id="import-from-github"><i class="bi bi-github me-2"></i>From GitHub</a></li>
  141. </ul>
  142. </div>
  143. <input type="file" id="file-input" class="file-input" accept=".md,.markdown,text/markdown">
  144. <div class="dropdown">
  145. <button class="tool-button dropdown-toggle" type="button" id="exportDropdown" data-bs-toggle="dropdown" aria-expanded="false" title="Export Markdown">
  146. <i class="bi bi-download"></i> <span class="btn-text">Export</span>
  147. </button>
  148. <ul class="dropdown-menu" aria-labelledby="exportDropdown">
  149. <li><a class="dropdown-item" href="#" id="export-md"><i class="bi bi-file-earmark-text me-2"></i>Markdown (.md)</a></li>
  150. <li><a class="dropdown-item" href="#" id="export-html"><i class="bi bi-file-earmark-code me-2"></i>HTML</a></li>
  151. <li><a class="dropdown-item" href="#" id="export-pdf"><i class="bi bi-file-earmark-pdf me-2"></i>PDF</a></li>
  152. </ul>
  153. </div>
  154. <button id="copy-markdown-button" class="tool-button" title="Copy Markdown">
  155. <i class="bi bi-clipboard"></i> <span class="btn-text">Copy</span>
  156. </button>
  157. <button id="share-button" class="tool-button" title="Share via URL">
  158. <i class="bi bi-share"></i> <span class="btn-text">Share</span>
  159. </button>
  160. <div class="dropdown me-1">
  161. <button class="tool-button dropdown-toggle" type="button" id="languageDropdown" data-bs-toggle="dropdown" aria-expanded="false" title="Switch Language">
  162. <i class="bi bi-translate"></i> <span id="current-lang-label" class="btn-text">English</span>
  163. </button>
  164. <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="languageDropdown">
  165. <li><a class="dropdown-item lang-select-item active" href="#" data-lang="en">🇺🇸 English</a></li>
  166. <li><a class="dropdown-item lang-select-item" href="#" data-lang="zh">🇨🇳 简体中文</a></li>
  167. <li><a class="dropdown-item lang-select-item" href="#" data-lang="ja">🇯🇵 日本語</a></li>
  168. <li><a class="dropdown-item lang-select-item" href="#" data-lang="ko">🇰🇷 한국어</a></li>
  169. <li><a class="dropdown-item lang-select-item" href="#" data-lang="pt">🇧🇷 Português (Brasil)</a></li>
  170. <li><a class="dropdown-item lang-select-item" href="#" data-lang="es">🇪🇸 Español</a></li>
  171. <li><a class="dropdown-item lang-select-item" href="#" data-lang="fr">🇫🇷 Français</a></li>
  172. <li><a class="dropdown-item lang-select-item" href="#" data-lang="de">🇩🇪 Deutsch</a></li>
  173. <li><a class="dropdown-item lang-select-item" href="#" data-lang="ru">🇷🇺 Русский</a></li>
  174. <li><a class="dropdown-item lang-select-item" href="#" data-lang="it">🇮🇹 Italiano</a></li>
  175. <li><a class="dropdown-item lang-select-item" href="#" data-lang="tr">🇹🇷 Türkçe</a></li>
  176. <li><a class="dropdown-item lang-select-item" href="#" data-lang="pl">🇵🇱 Polski</a></li>
  177. <li><a class="dropdown-item lang-select-item" href="#" data-lang="tw">🇹🇼 繁體中文</a></li>
  178. <li><a class="dropdown-item lang-select-item" href="#" data-lang="uk">🇺🇦 Українська</a></li>
  179. </ul>
  180. </div>
  181. <button id="theme-toggle" class="tool-button" title="Toggle Dark Mode">
  182. <i class="bi bi-moon"></i>
  183. </button>
  184. </div>
  185. <!-- Hamburger menu for mobile -->
  186. <div class="mobile-menu d-md-none">
  187. <button id="mobile-menu-toggle" class="tool-button" title="Menu">
  188. <i class="bi bi-list"></i>
  189. </button>
  190. <div id="mobile-menu-panel" class="mobile-menu-panel">
  191. <div class="mobile-menu-header">
  192. <h2 class="h5 m-0">Menu</h2>
  193. <button id="close-mobile-menu" class="tool-button" aria-label="Close menu">
  194. <i class="bi bi-x-lg"></i>
  195. </button>
  196. </div>
  197. <!-- Mobile Document Tabs Section -->
  198. <div class="mobile-tabs-section mb-3">
  199. <div class="mobile-tabs-header">
  200. <span class="mobile-tabs-label"><i class="bi bi-files me-1"></i> Documents</span>
  201. <button id="mobile-new-tab-btn" class="mobile-new-tab-btn" title="New document" aria-label="New document">
  202. <i class="bi bi-plus-lg"></i>
  203. </button>
  204. </div>
  205. <div id="mobile-tab-list" class="mobile-tab-list" role="tablist" aria-label="Document tabs">
  206. <!-- Dynamically populated by JavaScript -->
  207. </div>
  208. <button id="mobile-tab-reset-btn" class="tab-reset-btn mt-2 w-100" title="Reset all files" aria-label="Reset all files">
  209. <i class="bi bi-arrow-counterclockwise"></i> Reset all files
  210. </button>
  211. </div>
  212. <!-- Story 1.4: Mobile View Mode Buttons -->
  213. <div class="mobile-view-mode-group mb-3" role="group" aria-label="View mode">
  214. <button class="mobile-view-mode-btn" data-mode="editor" aria-pressed="false" title="Editor only">
  215. <i class="bi bi-file-text"></i>
  216. <span>Editor</span>
  217. </button>
  218. <button class="mobile-view-mode-btn active" data-mode="split" aria-pressed="true" title="Split view">
  219. <i class="bi bi-layout-split"></i>
  220. <span>Split</span>
  221. </button>
  222. <button class="mobile-view-mode-btn" data-mode="preview" aria-pressed="false" title="Preview only">
  223. <i class="bi bi-eye"></i>
  224. <span>Preview</span>
  225. </button>
  226. </div>
  227. <div class="mobile-stats-container mb-3">
  228. <div class="stat-item mb-2">
  229. <i class="bi bi-clock me-1"></i> <span id="mobile-reading-time">0</span> <span id="lbl-mobile-min-read">Min Read</span>
  230. </div>
  231. <div class="stat-item mb-2">
  232. <i class="bi bi-text-paragraph me-1"></i> <span id="mobile-word-count">0</span> <span id="lbl-mobile-words">Words</span>
  233. </div>
  234. <div class="stat-item">
  235. <i class="bi bi-fonts me-1"></i> <span id="mobile-char-count">0</span> <span id="lbl-mobile-chars">Chars</span>
  236. </div>
  237. </div>
  238. <div class="mobile-menu-items">
  239. <button id="mobile-toggle-sync" class="mobile-menu-item tool-button sync-enabled sync-active" title="Toggle Sync Scrolling">
  240. <i class="bi bi-link"></i> Sync Off
  241. </button>
  242. <button id="mobile-import-button" class="mobile-menu-item" title="Import from files">
  243. <i class="bi bi-upload me-2"></i> Import from files
  244. </button>
  245. <button id="mobile-import-github-button" class="mobile-menu-item" title="Import from GitHub">
  246. <i class="bi bi-github me-2"></i> Import from GitHub
  247. </button>
  248. <button id="mobile-export-md" class="mobile-menu-item" title="Export as Markdown">
  249. <i class="bi bi-file-earmark-text me-2"></i> Export as Markdown
  250. </button>
  251. <button id="mobile-export-html" class="mobile-menu-item" title="Export as HTML">
  252. <i class="bi bi-file-earmark-code me-2"></i> Export as HTML
  253. </button>
  254. <button id="mobile-export-pdf" class="mobile-menu-item" title="Export as PDF">
  255. <i class="bi bi-file-earmark-pdf me-2"></i> Export as PDF
  256. </button>
  257. <button id="mobile-copy-markdown" class="mobile-menu-item" title="Copy Markdown">
  258. <i class="bi bi-clipboard me-2"></i> Copy
  259. </button>
  260. <button id="mobile-share-button" class="mobile-menu-item" title="Share via URL">
  261. <i class="bi bi-share me-2"></i> Share
  262. </button>
  263. <div class="mobile-menu-item dropdown w-100 p-0 border-0">
  264. <button class="mobile-menu-item w-100 text-start dropdown-toggle" type="button" id="mobileLanguageDropdown" data-bs-toggle="dropdown" aria-expanded="false" title="Switch Language">
  265. <i class="bi bi-translate me-2"></i> Language: <span id="mobile-current-lang-label">English</span>
  266. </button>
  267. <ul class="dropdown-menu w-100" aria-labelledby="mobileLanguageDropdown">
  268. <li><a class="dropdown-item lang-select-item active" href="#" data-lang="en">us English</a></li>
  269. <li><a class="dropdown-item lang-select-item" href="#" data-lang="zh">CN 简体中文</a></li>
  270. <li><a class="dropdown-item lang-select-item" href="#" data-lang="ja">JP 日本語</a></li>
  271. <li><a class="dropdown-item lang-select-item" href="#" data-lang="ko">KR 한국어</a></li>
  272. <li><a class="dropdown-item lang-select-item" href="#" data-lang="pt">BR Português (Brasil)</a></li>
  273. <li><a class="dropdown-item lang-select-item" href="#" data-lang="es">ES Español</a></li>
  274. <li><a class="dropdown-item lang-select-item" href="#" data-lang="fr">FR Français</a></li>
  275. <li><a class="dropdown-item lang-select-item" href="#" data-lang="de">DE Deutsch</a></li>
  276. <li><a class="dropdown-item lang-select-item" href="#" data-lang="ru">RU Русский</a></li>
  277. <li><a class="dropdown-item lang-select-item" href="#" data-lang="it">IT Italiano</a></li>
  278. <li><a class="dropdown-item lang-select-item" href="#" data-lang="tr">TR Türkçe</a></li>
  279. <li><a class="dropdown-item lang-select-item" href="#" data-lang="pl">PL Polski</a></li>
  280. <li><a class="dropdown-item lang-select-item" href="#" data-lang="tw">TW 繁體中文</a></li>
  281. <li><a class="dropdown-item lang-select-item" href="#" data-lang="uk">UK Українська</a></li>
  282. </ul>
  283. </div>
  284. <button id="mobile-theme-toggle" class="mobile-menu-item" title="Toggle Dark Mode">
  285. <i class="bi bi-moon me-2"></i> Dark Mode
  286. </button>
  287. </div>
  288. </div>
  289. <div id="mobile-menu-overlay"></div>
  290. </div>
  291. </div>
  292. </header>
  293. <!-- Tab Bar -->
  294. <div class="tab-bar" id="tab-bar">
  295. <div class="tab-list" id="tab-list" role="tablist" aria-label="Document tabs"></div>
  296. <button class="tab-new-btn" id="tab-new-btn" title="New Tab (Ctrl+T)" aria-label="Open new tab">
  297. <i class="bi bi-plus-lg"></i> New Tab
  298. </button>
  299. <button class="tab-reset-btn" id="tab-reset-btn" title="Reset all files" aria-label="Reset all files">
  300. <i class="bi bi-arrow-counterclockwise"></i> Reset
  301. </button>
  302. </div>
  303. <!-- Markdown Formatting Toolbar -->
  304. <div class="markdown-format-toolbar" id="markdown-format-toolbar" role="toolbar" aria-label="Markdown formatting toolbar">
  305. <div class="markdown-toolbar-group">
  306. <button type="button" class="markdown-tool-btn" data-md-action="undo" title="Undo" aria-label="Undo"><i class="bi bi-arrow-counterclockwise"></i></button>
  307. <button type="button" class="markdown-tool-btn" data-md-action="redo" title="Redo" aria-label="Redo"><i class="bi bi-arrow-clockwise"></i></button>
  308. <button type="button" class="markdown-tool-btn" data-md-action="clear-formatting" title="Clear document" aria-label="Clear document"><i class="bi bi-eraser"></i></button>
  309. </div>
  310. <div class="markdown-toolbar-group">
  311. <button type="button" class="markdown-tool-btn" data-md-action="bold" title="Bold" aria-label="Bold"><i class="bi bi-type-bold"></i></button>
  312. <button type="button" class="markdown-tool-btn" data-md-action="strike" title="Strikethrough" aria-label="Strikethrough"><i class="bi bi-type-strikethrough"></i></button>
  313. <button type="button" class="markdown-tool-btn" data-md-action="italic" title="Italic" aria-label="Italic"><i class="bi bi-type-italic"></i></button>
  314. <button type="button" class="markdown-tool-btn" data-md-action="quote" title="Blockquote" aria-label="Blockquote"><i class="bi bi-quote"></i></button>
  315. <button type="button" class="markdown-tool-btn text-tool" data-md-action="title-case" title="Title case" aria-label="Title case">Aa</button>
  316. <button type="button" class="markdown-tool-btn text-tool" data-md-action="uppercase" title="Uppercase" aria-label="Uppercase">A</button>
  317. <button type="button" class="markdown-tool-btn text-tool" data-md-action="lowercase" title="Lowercase" aria-label="Lowercase">a</button>
  318. </div>
  319. <div class="markdown-toolbar-group">
  320. <button type="button" class="markdown-tool-btn" data-md-action="align-left" title="Align left" aria-label="Align left"><i class="bi bi-text-left"></i></button>
  321. <button type="button" class="markdown-tool-btn" data-md-action="align-center" title="Align center" aria-label="Align center"><i class="bi bi-text-center"></i></button>
  322. <button type="button" class="markdown-tool-btn" data-md-action="align-right" title="Align right" aria-label="Align right"><i class="bi bi-text-right"></i></button>
  323. <button type="button" id="direction-toggle" class="markdown-tool-btn text-tool" title="Switch to RTL" aria-label="Toggle text direction" aria-pressed="false">L</button>
  324. </div>
  325. <div class="markdown-toolbar-group heading-group">
  326. <button type="button" class="markdown-tool-btn text-tool" data-md-action="heading" data-md-level="1" title="Heading 1" aria-label="Heading 1">H1</button>
  327. <button type="button" class="markdown-tool-btn text-tool" data-md-action="heading" data-md-level="2" title="Heading 2" aria-label="Heading 2">H2</button>
  328. <button type="button" class="markdown-tool-btn text-tool" data-md-action="heading" data-md-level="3" title="Heading 3" aria-label="Heading 3">H3</button>
  329. <button type="button" class="markdown-tool-btn text-tool" data-md-action="heading" data-md-level="4" title="Heading 4" aria-label="Heading 4">H4</button>
  330. <button type="button" class="markdown-tool-btn text-tool" data-md-action="heading" data-md-level="5" title="Heading 5" aria-label="Heading 5">H5</button>
  331. <button type="button" class="markdown-tool-btn text-tool" data-md-action="heading" data-md-level="6" title="Heading 6" aria-label="Heading 6">H6</button>
  332. </div>
  333. <div class="markdown-toolbar-group">
  334. <button type="button" class="markdown-tool-btn" data-md-action="unordered-list" title="Bulleted list" aria-label="Bulleted list"><i class="bi bi-list-ul"></i></button>
  335. <button type="button" class="markdown-tool-btn" data-md-action="ordered-list" title="Numbered list" aria-label="Numbered list"><i class="bi bi-list-ol"></i></button>
  336. <button type="button" class="markdown-tool-btn" data-md-action="horizontal-rule" title="Horizontal rule" aria-label="Horizontal rule"><i class="bi bi-dash-lg"></i></button>
  337. </div>
  338. <div class="markdown-toolbar-group">
  339. <button type="button" class="markdown-tool-btn" data-md-action="link" title="Link" aria-label="Link"><i class="bi bi-link-45deg"></i></button>
  340. <button type="button" class="markdown-tool-btn text-tool" data-md-action="reference" title="Reference" aria-label="Reference"><i></i></button>
  341. <button type="button" class="markdown-tool-btn" data-md-action="image" title="Image" aria-label="Image"><i class="bi bi-card-image"></i></button>
  342. <button type="button" class="markdown-tool-btn" data-md-action="inline-code" title="Inline code" aria-label="Inline code"><i class="bi bi-code-slash"></i></button>
  343. <button type="button" class="markdown-tool-btn" data-md-action="code-block" title="Code block" aria-label="Code block"><i class="bi bi-file-code"></i></button>
  344. <button type="button" class="markdown-tool-btn" data-md-action="terminal-block" title="Terminal block" aria-label="Terminal block"><i class="bi bi-terminal"></i></button>
  345. <button type="button" class="markdown-tool-btn" data-md-action="table" title="Table" aria-label="Table"><i class="bi bi-table"></i></button>
  346. <button type="button" class="markdown-tool-btn" data-md-action="date-time" title="Date and time" aria-label="Date and time"><i class="bi bi-clock"></i></button>
  347. <button type="button" class="markdown-tool-btn" data-md-action="emoji" title="Emoji shortcode" aria-label="Emoji shortcode"><i class="bi bi-emoji-smile"></i></button>
  348. <button type="button" class="markdown-tool-btn" data-md-action="symbols" title="Symbols &amp; HTML entities" aria-label="Symbols &amp; HTML entities"><i class="bi bi-c-circle"></i></button>
  349. <button type="button" class="markdown-tool-btn" data-md-action="alert" title="Markdown alert" aria-label="Markdown alert"><i class="bi bi-newspaper"></i></button>
  350. </div>
  351. <div class="markdown-toolbar-group">
  352. <button type="button" class="markdown-tool-btn" data-md-action="fullscreen" title="Fullscreen" aria-label="Fullscreen"><i class="bi bi-arrows-fullscreen"></i></button>
  353. <button type="button" class="markdown-tool-btn" data-md-action="find" title="Find &amp; Replace" aria-label="Find &amp; Replace"><i class="bi bi-search"></i></button>
  354. <button type="button" class="markdown-tool-btn" data-md-action="help" title="Help" aria-label="Help"><i class="bi bi-question-circle"></i></button>
  355. <button type="button" class="markdown-tool-btn" data-md-action="info" title="About Markdown" aria-label="About Markdown"><i class="bi bi-info-circle"></i></button>
  356. </div>
  357. </div>
  358. <!-- Reset Confirmation Modal -->
  359. <div id="reset-confirm-modal" class="reset-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="reset-modal-title" aria-hidden="true" style="display:none;">
  360. <div class="reset-modal-box reset-modal-box--wide">
  361. <p id="reset-modal-title" class="reset-modal-message">Are you sure you want to delete all files?</p>
  362. <div class="reset-modal-actions">
  363. <button class="reset-modal-btn reset-modal-cancel" id="reset-modal-cancel">Cancel</button>
  364. <button class="reset-modal-btn reset-modal-confirm" id="reset-modal-confirm">Delete All</button>
  365. </div>
  366. </div>
  367. </div>
  368. <!-- Clear Markdown Formatting Modal -->
  369. <div id="clear-formatting-modal" class="reset-modal-overlay modal-overlay" role="dialog" aria-modal="true" aria-labelledby="clear-formatting-title" aria-hidden="true" style="display:none;">
  370. <div class="reset-modal-box reset-modal-box--wide modal-box">
  371. <div class="modal-header">
  372. <p id="clear-formatting-title" class="reset-modal-message">Clear active document?</p>
  373. <button type="button" class="modal-close-btn" id="clear-formatting-close" aria-label="Close clear document dialog">
  374. <i class="bi bi-x-lg"></i>
  375. </button>
  376. </div>
  377. <p class="modal-subtext">Are you sure you want to clear the content of the active document? The document itself will not be deleted.</p>
  378. <div class="reset-modal-actions">
  379. <button class="reset-modal-btn reset-modal-cancel" id="clear-formatting-cancel">Cancel</button>
  380. <button class="reset-modal-btn reset-modal-confirm" id="clear-formatting-confirm">Clear Document</button>
  381. </div>
  382. </div>
  383. </div>
  384. <!-- Find & Replace Floating Panel -->
  385. <div id="find-replace-modal" class="find-replace-panel" role="region" aria-label="Find and Replace" style="display:none;">
  386. <div class="find-replace-header" id="find-replace-drag-handle">
  387. <span class="find-replace-title"><i class="bi bi-search me-1"></i> Find &amp; Replace</span>
  388. <div class="find-replace-header-actions">
  389. <button type="button" class="panel-icon-btn" id="find-replace-reset" title="Reset Position" aria-label="Reset Position"><i class="bi bi-arrow-counterclockwise"></i></button>
  390. <button type="button" class="panel-icon-btn" id="find-replace-dock" title="Toggle Dock Mode" aria-label="Toggle Dock Mode"><i class="bi bi-layout-sidebar-reverse"></i></button>
  391. <button type="button" class="panel-icon-btn" id="find-replace-close-icon" aria-label="Close find and replace panel"><i class="bi bi-x-lg"></i></button>
  392. </div>
  393. </div>
  394. <div class="find-replace-body">
  395. <!-- Find Row -->
  396. <div class="find-replace-field-row">
  397. <div class="find-input-container">
  398. <input type="text" id="find-replace-input" class="find-input-field" placeholder="Find" aria-label="Find query" />
  399. <div class="find-options-group">
  400. <button type="button" class="find-option-btn" id="find-case" title="Match Case (Aa)" aria-label="Match Case">Aa</button>
  401. <button type="button" class="find-option-btn" id="find-word" title="Match Whole Word (W)" aria-label="Match Whole Word">W</button>
  402. <button type="button" class="find-option-btn" id="find-regex" title="Use Regular Expression (.*)" aria-label="Use Regular Expression">.*</button>
  403. <button type="button" class="find-option-btn" id="find-sel" title="Find in Selection (Sel)" aria-label="Find in Selection"><i class="bi bi-align-start"></i></button>
  404. </div>
  405. </div>
  406. </div>
  407. <!-- Real-time Regex Error Box -->
  408. <div id="find-replace-error" class="find-error-drawer" style="display:none;">
  409. <i class="bi bi-exclamation-triangle-fill me-1"></i> <span id="regex-error-msg"></span>
  410. </div>
  411. <!-- Replace Row -->
  412. <div class="find-replace-field-row">
  413. <div class="replace-input-container">
  414. <input type="text" id="find-replace-with" class="find-input-field" placeholder="Replace" aria-label="Replace with" />
  415. <div class="find-options-group">
  416. <button type="button" class="find-option-btn" id="replace-preserve-case" title="Preserve Case (Ab)" aria-label="Preserve Case">Ab</button>
  417. <button type="button" class="find-option-btn active" id="find-wrap" title="Wrap Around (Wrap)" aria-label="Wrap Around" aria-pressed="true">Wrap</button>
  418. </div>
  419. </div>
  420. </div>
  421. <!-- Meta Controls Row -->
  422. <div class="find-replace-meta-row">
  423. <span id="find-replace-count" class="find-match-count" role="status" aria-live="polite">0 of 0 matches</span>
  424. <div class="find-nav-group">
  425. <button type="button" class="find-nav-arrow-btn" id="find-prev" title="Previous match (Shift+Enter)" aria-label="Previous match" disabled>
  426. <i class="bi bi-chevron-up"></i>
  427. </button>
  428. <button type="button" class="find-nav-arrow-btn" id="find-next" title="Next match (Enter)" aria-label="Next match" disabled>
  429. <i class="bi bi-chevron-down"></i>
  430. </button>
  431. </div>
  432. </div>
  433. <!-- Advanced Drawer Toggle -->
  434. <div class="find-drawer-toggle-row">
  435. <button type="button" class="drawer-toggle-btn" id="fr-drawer-toggle" aria-expanded="false">
  436. <i class="bi bi-chevron-right me-1"></i> Advanced Options
  437. </button>
  438. </div>
  439. <!-- Collapsible Drawer -->
  440. <div id="fr-drawer-content" class="find-replace-drawer-content" style="display:none;">
  441. <div class="drawer-field">
  442. <label for="find-replace-scope" class="drawer-label">Scope Filter</label>
  443. <select id="find-replace-scope" class="drawer-select">
  444. <option value="entire">Entire Document</option>
  445. <option value="heading">Headings only</option>
  446. <option value="code">Code blocks only</option>
  447. <option value="latex">LaTeX blocks only</option>
  448. <option value="mermaid">Mermaid blocks only</option>
  449. <option value="plain">Plain text only</option>
  450. </select>
  451. </div>
  452. <div class="drawer-field">
  453. <label for="find-replace-history" class="drawer-label">Search History</label>
  454. <select id="find-replace-history" class="drawer-select">
  455. <option value="">Recent queries...</option>
  456. </select>
  457. </div>
  458. <div class="drawer-field check-field">
  459. <input type="checkbox" id="find-replace-diff-toggle" class="drawer-checkbox" />
  460. <label for="find-replace-diff-toggle" class="drawer-label-checkbox">Show Diff Preview before replace</label>
  461. </div>
  462. </div>
  463. </div>
  464. <!-- Actions Footer -->
  465. <div class="find-replace-actions-footer">
  466. <button type="button" class="fr-action-btn" id="find-replace-current" disabled>Replace</button>
  467. <button type="button" class="fr-action-btn" id="find-replace-all" disabled>Replace All</button>
  468. <button type="button" class="fr-action-btn secondary" id="find-replace-reset-footer" title="Reset Position">Reset</button>
  469. <button type="button" class="fr-action-btn secondary" id="find-replace-close">Close</button>
  470. </div>
  471. </div>
  472. <!-- Diff Preview Modal -->
  473. <div id="find-replace-diff-modal" class="reset-modal-overlay modal-overlay" role="dialog" aria-modal="true" aria-labelledby="diff-modal-title" aria-hidden="true" style="display:none;">
  474. <div class="reset-modal-box reset-modal-box--xl modal-box">
  475. <div class="modal-header">
  476. <p id="diff-modal-title" class="reset-modal-message">Replace All Diff Preview</p>
  477. <button type="button" class="modal-close-btn" id="find-replace-diff-close-icon" aria-label="Close diff preview dialog">
  478. <i class="bi bi-x-lg"></i>
  479. </button>
  480. </div>
  481. <div class="modal-body diff-preview-body">
  482. <p class="modal-subtext">Review the proposed changes before committing them to the document.</p>
  483. <div class="diff-container" id="find-replace-diff-container">
  484. <!-- Populated dynamically -->
  485. </div>
  486. </div>
  487. <div class="reset-modal-actions">
  488. <button class="reset-modal-btn reset-modal-cancel" id="find-replace-diff-cancel">Cancel</button>
  489. <button class="reset-modal-btn reset-modal-confirm" id="find-replace-diff-confirm">Commit Replacements</button>
  490. </div>
  491. </div>
  492. </div>
  493. <!-- Help Modal -->
  494. <div id="help-modal" class="reset-modal-overlay modal-overlay" role="dialog" aria-modal="true" aria-labelledby="help-modal-title" aria-hidden="true" style="display:none;">
  495. <div class="reset-modal-box reset-modal-box--xl modal-box">
  496. <div class="modal-header">
  497. <p id="help-modal-title" class="reset-modal-message">Markdown ++ Help</p>
  498. <button type="button" class="modal-close-btn" id="help-modal-close-icon" aria-label="Close help dialog">
  499. <i class="bi bi-x-lg"></i>
  500. </button>
  501. </div>
  502. <div class="modal-body">
  503. <div class="modal-section">
  504. <h3 class="modal-section-title">Application shortcuts</h3>
  505. <ul class="modal-list">
  506. <li>Use the view buttons in the toolbar to switch between Editor, Split, and Preview modes.</li>
  507. <li>Sync scrolling is available in Split view to keep the editor and preview aligned.</li>
  508. <li>Import, Export, Copy, Share, and Theme toggle actions are always available in the header toolbar.</li>
  509. </ul>
  510. </div>
  511. <div class="modal-section">
  512. <h3 class="modal-section-title">Toolbar descriptions</h3>
  513. <ul class="modal-list">
  514. <li>Undo/Redo and Clear Formatting help you manage editing changes quickly.</li>
  515. <li>Text styling tools cover bold, italic, strikethrough, quotes, headings, and list formatting.</li>
  516. <li>Insert helpers add links, images, code blocks, tables, emojis, symbols, and alerts.</li>
  517. <li>Use Fullscreen, Find &amp; Replace, Help, and About Markdown for focused editing.</li>
  518. </ul>
  519. </div>
  520. <div class="modal-section">
  521. <h3 class="modal-section-title">Markdown tips</h3>
  522. <ul class="modal-list">
  523. <li>Create headings with <code>#</code>, <code>##</code>, and <code>###</code> prefixes.</li>
  524. <li>Emphasize text with <code>**bold**</code>, <code>*italic*</code>, or <code>~~strikethrough~~</code>.</li>
  525. <li>Use <code>-</code> or <code>1.</code> to build lists, and triple backticks for code blocks.</li>
  526. </ul>
  527. </div>
  528. <div class="modal-section">
  529. <h3 class="modal-section-title">Keyboard shortcuts</h3>
  530. <ul class="modal-list">
  531. <li><kbd>Ctrl</kbd>/<kbd>⌘</kbd> + <kbd>Z</kbd> &mdash; Undo</li>
  532. <li><kbd>Ctrl</kbd>/<kbd>⌘</kbd> + <kbd>Shift</kbd> + <kbd>Z</kbd> &mdash; Redo</li>
  533. <li><kbd>Ctrl</kbd>/<kbd>⌘</kbd> + <kbd>F</kbd> &mdash; Open Find &amp; Replace</li>
  534. <li><kbd>Ctrl</kbd>/<kbd>⌘</kbd> + <kbd>C</kbd>/<kbd>V</kbd> &mdash; Copy/Paste</li>
  535. </ul>
  536. </div>
  537. </div>
  538. <div class="reset-modal-actions">
  539. <button class="reset-modal-btn reset-modal-cancel" id="help-modal-close">Close</button>
  540. </div>
  541. </div>
  542. </div>
  543. <!-- About Markdown Modal -->
  544. <div id="about-modal" class="reset-modal-overlay modal-overlay" role="dialog" aria-modal="true" aria-labelledby="about-modal-title" aria-hidden="true" style="display:none;">
  545. <div class="reset-modal-box reset-modal-box--xl modal-box">
  546. <div class="modal-header">
  547. <p id="about-modal-title" class="reset-modal-message">About Markdown</p>
  548. <button type="button" class="modal-close-btn" id="about-modal-close-icon" aria-label="Close about dialog">
  549. <i class="bi bi-x-lg"></i>
  550. </button>
  551. </div>
  552. <div class="modal-body">
  553. <div class="about-header">
  554. <img src="assets/icon.jpg" alt="Markdown ++ logo" class="about-logo" width="64" height="64" />
  555. <div class="about-details">
  556. <h3 class="about-title">Markdown ++</h3>
  557. <p class="about-description">A GitHub-style Markdown editor with live preview, diagrams, math, syntax highlighting, and export tools.</p>
  558. <p class="about-meta">Version <span id="about-version"></span> &bull; Apache License 2.0 &bull; Open source</p>
  559. </div>
  560. </div>
  561. <div class="modal-section">
  562. <h3 class="modal-section-title">Open-source links</h3>
  563. <ul class="modal-list">
  564. <li><a href="https://git.4parv.in/parv.ashwani/markdownplusplus/blob/main/LICENSE" target="_blank" rel="noopener noreferrer">Apache License 2.0</a></li>
  565. <li><a href="https://git.4parv.in/parv.ashwani/markdownplusplus" target="_blank" rel="noopener noreferrer">GitHub Repository</a></li>
  566. <li><a href="https://git.4parv.in/parv.ashwani/markdownplusplus/wiki/Contributing" target="_blank" rel="noopener noreferrer">Contribution Guide</a></li>
  567. <li><a href="https://git.4parv.in/parv.ashwani/markdownplusplus/issues/new/choose" target="_blank" rel="noopener noreferrer">Report an Issue</a></li>
  568. <li><a href="https://git.4parv.in/parv.ashwani/markdownplusplus/discussions" target="_blank" rel="noopener noreferrer">Community &amp; Support</a></li>
  569. </ul>
  570. <p class="modal-subtext">For feature requests, open a GitHub issue or start a discussion so the community can weigh in.</p>
  571. </div>
  572. <div class="modal-section">
  573. <h3 class="modal-section-title">Markdown resources</h3>
  574. <ul class="modal-list">
  575. <li><a href="https://git.4parv.in/parv.ashwani/markdownplusplus/wiki/Markdown-Reference" target="_blank" rel="noopener noreferrer">Markdown syntax reference</a></li>
  576. </ul>
  577. </div>
  578. <div class="modal-section">
  579. <h3 class="modal-section-title">Technology stack</h3>
  580. <ul class="modal-list">
  581. <li>HTML, CSS, and JavaScript with Bootstrap 5 for layout and styling.</li>
  582. <li>Marked, DOMPurify, Highlight.js, Mermaid, MathJax, and Emoji Toolkit for rendering.</li>
  583. </ul>
  584. </div>
  585. <div class="modal-section">
  586. <h3 class="modal-section-title">Open-source credits</h3>
  587. <p class="modal-subtext">Markdown ++ is built on top of open-source libraries maintained by the community. Thank you to every contributor and maintainer.</p>
  588. </div>
  589. </div>
  590. <div class="reset-modal-actions">
  591. <button class="reset-modal-btn reset-modal-cancel" id="about-modal-close">Close</button>
  592. </div>
  593. </div>
  594. </div>
  595. <!-- Share Modal -->
  596. <div id="share-modal" class="reset-modal-overlay modal-overlay" role="dialog" aria-modal="true" aria-labelledby="share-modal-title" aria-hidden="true" style="display:none;">
  597. <div class="reset-modal-box reset-modal-box--wide modal-box">
  598. <div class="modal-header">
  599. <p id="share-modal-title" class="reset-modal-message">Share Document</p>
  600. <button type="button" class="modal-close-btn" id="share-modal-close-icon" aria-label="Close share dialog">
  601. <i class="bi bi-x-lg"></i>
  602. </button>
  603. </div>
  604. <div class="modal-body">
  605. <p class="share-modal-description">Choose how recipients can interact with this document.</p>
  606. <div class="share-mode-cards">
  607. <label class="share-mode-card" id="share-card-view" for="share-mode-view">
  608. <input type="radio" id="share-mode-view" name="share-mode" value="view" checked />
  609. <span class="share-card-icon"><i class="bi bi-eye"></i></span>
  610. <span class="share-card-body">
  611. <span class="share-card-title">View only</span>
  612. <span class="share-card-desc">Opens in preview mode. The editor is hidden.</span>
  613. </span>
  614. <span class="share-card-check"><i class="bi bi-check-lg"></i></span>
  615. </label>
  616. <label class="share-mode-card" id="share-card-edit" for="share-mode-edit">
  617. <input type="radio" id="share-mode-edit" name="share-mode" value="edit" />
  618. <span class="share-card-icon"><i class="bi bi-pencil-square"></i></span>
  619. <span class="share-card-body">
  620. <span class="share-card-title">Edit</span>
  621. <span class="share-card-desc">Opens in split editor + preview mode.</span>
  622. </span>
  623. <span class="share-card-check"><i class="bi bi-check-lg"></i></span>
  624. </label>
  625. </div>
  626. <div class="share-url-row">
  627. <input type="text" id="share-url-input" class="rename-modal-input share-url-input" readonly placeholder="Generating link…" aria-label="Share URL" />
  628. <button class="reset-modal-btn share-copy-btn" id="share-copy-btn" title="Copy link">
  629. <i class="bi bi-clipboard"></i>
  630. </button>
  631. </div>
  632. <p class="share-modal-notice"><i class="bi bi-info-circle"></i> The entire document is encoded in the URL. No data is sent to any server.</p>
  633. </div>
  634. <div class="reset-modal-actions">
  635. <button class="reset-modal-btn reset-modal-cancel" id="share-modal-close">Close</button>
  636. </div>
  637. </div>
  638. </div>
  639. <!-- Rename Modal -->
  640. <div id="rename-modal" class="reset-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="rename-modal-title" aria-hidden="true" style="display:none;">
  641. <div class="reset-modal-box reset-modal-box--wide">
  642. <p id="rename-modal-title" class="reset-modal-message">Rename file</p>
  643. <input type="text" id="rename-modal-input" class="rename-modal-input" placeholder="File name" />
  644. <div class="reset-modal-actions">
  645. <button class="reset-modal-btn reset-modal-cancel" id="rename-modal-cancel">Cancel</button>
  646. <button class="reset-modal-btn reset-modal-confirm" id="rename-modal-confirm">Rename</button>
  647. </div>
  648. </div>
  649. </div>
  650. <!-- Link Modal -->
  651. <div id="link-modal" class="reset-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="link-modal-title" aria-hidden="true" style="display:none;">
  652. <div class="reset-modal-box reset-modal-box--wide">
  653. <p id="link-modal-title" class="reset-modal-message">Insert link</p>
  654. <div class="reset-modal-field">
  655. <label class="reset-modal-label" for="link-modal-url">Address / URL</label>
  656. <input type="url" id="link-modal-url" class="rename-modal-input" value="https://" />
  657. </div>
  658. <div class="reset-modal-field">
  659. <label class="reset-modal-label" for="link-modal-text">Link Text</label>
  660. <input type="text" id="link-modal-text" class="rename-modal-input" placeholder="Link title" />
  661. </div>
  662. <div class="reset-modal-actions">
  663. <button class="reset-modal-btn reset-modal-cancel" id="link-modal-cancel">Cancel</button>
  664. <button class="reset-modal-btn" id="link-modal-apply">Apply</button>
  665. </div>
  666. </div>
  667. </div>
  668. <!-- Reference Modal -->
  669. <div id="reference-modal" class="reset-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="reference-modal-title" aria-hidden="true" style="display:none;">
  670. <div class="reset-modal-box reset-modal-box--wide">
  671. <p id="reference-modal-title" class="reset-modal-message">Insert reference</p>
  672. <div class="reset-modal-field">
  673. <label class="reset-modal-label" for="reference-modal-number">Reference Number</label>
  674. <input type="text" id="reference-modal-number" class="rename-modal-input" value="[1]" />
  675. </div>
  676. <div class="reset-modal-field">
  677. <label class="reset-modal-label" for="reference-modal-url">Address / Link</label>
  678. <input type="url" id="reference-modal-url" class="rename-modal-input" value="https://" />
  679. </div>
  680. <div class="reset-modal-field">
  681. <label class="reset-modal-label" for="reference-modal-title-input">Title</label>
  682. <input type="text" id="reference-modal-title-input" class="rename-modal-input" placeholder="Reference title" />
  683. </div>
  684. <div class="reset-modal-actions">
  685. <button class="reset-modal-btn reset-modal-cancel" id="reference-modal-cancel">Cancel</button>
  686. <button class="reset-modal-btn" id="reference-modal-apply">Insert</button>
  687. </div>
  688. </div>
  689. </div>
  690. <!-- Image Modal -->
  691. <div id="image-modal" class="reset-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="image-modal-title" aria-hidden="true" style="display:none;">
  692. <div class="reset-modal-box reset-modal-box--wide">
  693. <p id="image-modal-title" class="reset-modal-message">Insert image</p>
  694. <div class="reset-modal-toggle-group">
  695. <label class="reset-modal-option">
  696. <input type="radio" name="image-source" id="image-source-upload" value="upload">
  697. Upload from Device
  698. </label>
  699. <label class="reset-modal-option">
  700. <input type="radio" name="image-source" id="image-source-url" value="url" checked>
  701. External Image (URL)
  702. </label>
  703. </div>
  704. <div id="image-upload-fields" class="reset-modal-field-group" style="display:none;">
  705. <input type="file" id="image-modal-file" class="rename-modal-input" accept="image/*" />
  706. </div>
  707. <div id="image-url-fields" class="reset-modal-field-group">
  708. <div class="reset-modal-field">
  709. <label class="reset-modal-label" for="image-modal-url">Image URL</label>
  710. <input type="url" id="image-modal-url" class="rename-modal-input" value="https://" />
  711. </div>
  712. </div>
  713. <div class="reset-modal-field">
  714. <label class="reset-modal-label" for="image-modal-alt">Alt Text (used for title)</label>
  715. <input type="text" id="image-modal-alt" class="rename-modal-input" placeholder="Image description" />
  716. </div>
  717. <div class="reset-modal-actions">
  718. <button class="reset-modal-btn reset-modal-cancel" id="image-modal-cancel">Cancel</button>
  719. <button class="reset-modal-btn" id="image-modal-insert">Insert</button>
  720. </div>
  721. </div>
  722. </div>
  723. <!-- Table Modal -->
  724. <div id="table-modal" class="reset-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="table-modal-title" aria-hidden="true" style="display:none;">
  725. <div class="reset-modal-box reset-modal-box--wide">
  726. <p id="table-modal-title" class="reset-modal-message">Insert table</p>
  727. <div class="reset-modal-field">
  728. <label class="reset-modal-label" for="table-modal-columns">Column count</label>
  729. <input type="number" id="table-modal-columns" class="rename-modal-input" min="1" max="20" value="3" />
  730. </div>
  731. <div class="reset-modal-field">
  732. <label class="reset-modal-label" for="table-modal-rows">Row count</label>
  733. <input type="number" id="table-modal-rows" class="rename-modal-input" min="1" max="20" value="1" />
  734. </div>
  735. <div class="reset-modal-actions">
  736. <button class="reset-modal-btn reset-modal-cancel" id="table-modal-cancel">Cancel</button>
  737. <button class="reset-modal-btn" id="table-modal-insert">Insert</button>
  738. </div>
  739. </div>
  740. </div>
  741. <!-- Emoji Modal -->
  742. <div id="emoji-modal" class="reset-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="emoji-modal-title" aria-hidden="true" style="display:none;">
  743. <div class="reset-modal-box reset-modal-box--wide reset-modal-box--xl">
  744. <p id="emoji-modal-title" class="reset-modal-message">GitHub Emojis</p>
  745. <div class="reset-modal-field">
  746. <label class="reset-modal-label" for="emoji-modal-search">Search</label>
  747. <input type="text" id="emoji-modal-search" class="rename-modal-input" placeholder="Search emojis" />
  748. </div>
  749. <div id="emoji-modal-grid" class="emoji-grid" role="listbox" aria-label="Emoji list"></div>
  750. <p id="emoji-modal-empty" class="modal-empty" style="display:none;">No emojis found.</p>
  751. <div class="reset-modal-actions">
  752. <button class="reset-modal-btn reset-modal-cancel" id="emoji-modal-cancel">Cancel</button>
  753. <button class="reset-modal-btn" id="emoji-modal-insert">Insert</button>
  754. </div>
  755. </div>
  756. </div>
  757. <!-- Symbols Modal -->
  758. <div id="symbols-modal" class="reset-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="symbols-modal-title" aria-hidden="true" style="display:none;">
  759. <div class="reset-modal-box reset-modal-box--wide reset-modal-box--xl">
  760. <p id="symbols-modal-title" class="reset-modal-message">Symbols &amp; HTML Entities</p>
  761. <div class="reset-modal-field">
  762. <label class="reset-modal-label" for="symbols-modal-search">Search</label>
  763. <input type="text" id="symbols-modal-search" class="rename-modal-input" placeholder="Search symbols" />
  764. </div>
  765. <div id="symbols-modal-grid" class="symbol-grid" role="listbox" aria-label="Symbol list"></div>
  766. <p id="symbols-modal-empty" class="modal-empty" style="display:none;">No symbols found.</p>
  767. <div class="reset-modal-actions">
  768. <button class="reset-modal-btn reset-modal-cancel" id="symbols-modal-cancel">Cancel</button>
  769. <button class="reset-modal-btn" id="symbols-modal-insert">Insert</button>
  770. </div>
  771. </div>
  772. </div>
  773. <!-- Markdown Alert Modal -->
  774. <div id="alert-modal" class="reset-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="alert-modal-title" aria-hidden="true" style="display:none;">
  775. <div class="reset-modal-box reset-modal-box--wide">
  776. <p id="alert-modal-title" class="reset-modal-message">Markdown alerts</p>
  777. <div id="alert-modal-grid" class="alert-grid" role="listbox" aria-label="Markdown alert types"></div>
  778. <div class="reset-modal-actions">
  779. <button class="reset-modal-btn reset-modal-cancel" id="alert-modal-cancel">Cancel</button>
  780. <button class="reset-modal-btn" id="alert-modal-insert">Insert</button>
  781. </div>
  782. </div>
  783. </div>
  784. <!-- GitHub Import Modal -->
  785. <div id="github-import-modal" class="reset-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="github-import-title" aria-hidden="true" style="display:none;">
  786. <div class="reset-modal-box">
  787. <p id="github-import-title" class="reset-modal-message">Import Markdown from GitHub</p>
  788. <input type="url" id="github-import-url" class="rename-modal-input" placeholder="https://github.com/owner/repo/blob/main/README.md" />
  789. <select id="github-import-file-select" class="rename-modal-input" style="display:none;"></select>
  790. <div id="github-import-selection-toolbar" class="github-import-selection-toolbar" style="display:none;">
  791. <span id="github-import-selected-count" class="github-import-selected-count">0 selected</span>
  792. <button type="button" class="reset-modal-btn" id="github-import-select-all">Select All</button>
  793. </div>
  794. <div id="github-import-tree" class="github-import-tree" style="display:none;"></div>
  795. <p id="github-import-error" class="github-import-error" style="display:none;"></p>
  796. <div class="reset-modal-actions">
  797. <button class="reset-modal-btn reset-modal-cancel" id="github-import-cancel">Cancel</button>
  798. <button class="reset-modal-btn" id="github-import-submit">Import</button>
  799. </div>
  800. </div>
  801. </div>
  802. <!-- Full-screen drag overlay (shown when a file is dragged over the window) -->
  803. <div id="drag-overlay" class="drag-overlay" aria-hidden="true">
  804. <div class="drag-overlay-inner">
  805. <i class="bi bi-cloud-arrow-up drag-overlay-icon"></i>
  806. <p class="drag-overlay-text">Drop your Markdown file anywhere</p>
  807. <p class="drag-overlay-sub">.md or .markdown files supported</p>
  808. </div>
  809. </div>
  810. <main class="content-container">
  811. <div class="editor-pane is-loading">
  812. <div id="line-numbers" class="line-numbers" aria-hidden="true" inert></div>
  813. <div id="editor-highlight-layer" class="editor-highlight-layer" aria-hidden="true" tabindex="-1" inert></div>
  814. <div class="editor-skeleton" id="editor-skeleton" aria-hidden="true">
  815. <div class="skeleton-placeholder skeleton-title"></div>
  816. <div class="skeleton-placeholder skeleton-line skeleton-w90"></div>
  817. <div class="skeleton-placeholder skeleton-line skeleton-w85"></div>
  818. <div class="skeleton-placeholder skeleton-line skeleton-w60"></div>
  819. <div class="skeleton-placeholder skeleton-subtitle"></div>
  820. <div class="skeleton-placeholder skeleton-line skeleton-w88"></div>
  821. <div class="skeleton-placeholder skeleton-line skeleton-w92"></div>
  822. <div class="skeleton-placeholder skeleton-line skeleton-w45"></div>
  823. </div>
  824. <textarea id="markdown-editor" placeholder="Type or paste your Markdown here..."></textarea>
  825. <div class="drop-hint" aria-hidden="true">
  826. <i class="bi bi-cloud-arrow-up me-1"></i>Drop a .md file anywhere to open it
  827. </div>
  828. </div>
  829. <!-- Resize Divider - Story 1.3 -->
  830. <div class="resize-divider" role="separator" aria-orientation="vertical" aria-label="Resize panes" tabindex="0">
  831. <div class="resize-divider-handle"></div>
  832. </div>
  833. <div class="preview-pane">
  834. <div id="markdown-preview" class="markdown-body">
  835. <!-- Initial dynamic article skeleton loader -->
  836. <div class="skeleton-preview-container" id="markdown-preview-skeleton" aria-hidden="true">
  837. <div class="skeleton-placeholder skeleton-title"></div>
  838. <div class="skeleton-placeholder skeleton-line skeleton-w90"></div>
  839. <div class="skeleton-placeholder skeleton-line skeleton-w85"></div>
  840. <div class="skeleton-placeholder skeleton-line skeleton-w60"></div>
  841. <div class="skeleton-placeholder skeleton-subtitle"></div>
  842. <div class="skeleton-placeholder skeleton-line skeleton-w88"></div>
  843. <div class="skeleton-placeholder skeleton-line skeleton-w92"></div>
  844. <div class="skeleton-placeholder skeleton-line skeleton-w45"></div>
  845. </div>
  846. </div>
  847. </div>
  848. </main>
  849. </div>
  850. <!-- Mermaid Zoom Modal -->
  851. <div id="mermaid-zoom-modal" role="dialog" aria-modal="true" aria-label="Diagram zoom view" aria-hidden="true">
  852. <div class="mermaid-modal-content">
  853. <div class="mermaid-modal-header">
  854. <span>Diagram</span>
  855. <button class="mermaid-modal-close" id="mermaid-modal-close" title="Close" aria-label="Close diagram modal">
  856. <i class="bi bi-x-lg"></i>
  857. </button>
  858. </div>
  859. <div class="mermaid-modal-diagram" id="mermaid-modal-diagram"></div>
  860. <div class="mermaid-modal-controls">
  861. <button class="mermaid-toolbar-btn" id="mermaid-modal-zoom-in" title="Zoom in">
  862. <i class="bi bi-zoom-in"></i> Zoom In
  863. </button>
  864. <button class="mermaid-toolbar-btn" id="mermaid-modal-zoom-out" title="Zoom out">
  865. <i class="bi bi-zoom-out"></i> Zoom Out
  866. </button>
  867. <button class="mermaid-toolbar-btn" id="mermaid-modal-zoom-reset" title="Reset zoom">
  868. <i class="bi bi-arrows-angle-contract"></i> Reset
  869. </button>
  870. <button class="mermaid-toolbar-btn" id="mermaid-modal-copy" title="Copy image">
  871. <i class="bi bi-clipboard-image"></i> Copy
  872. </button>
  873. <button class="mermaid-toolbar-btn" id="mermaid-modal-download-png" title="Download PNG">
  874. <i class="bi bi-file-image"></i> PNG
  875. </button>
  876. <button class="mermaid-toolbar-btn" id="mermaid-modal-download-svg" title="Download SVG">
  877. <i class="bi bi-filetype-svg"></i> SVG
  878. </button>
  879. </div>
  880. </div>
  881. </div>
  882. <script type="text/markdown" id="default-markdown">---
  883. title: Welcome to Markdown Plus Plus
  884. description: A GitHub-style Markdown renderer with live preview, math, diagrams, and export support.
  885. author: Parv Ashwani
  886. tags: ["markdown", "preview", "mermaid", "latex", "open-source"]
  887. ---
  888. # Welcome to Markdown ++
  889. ## ✨ Key Features
  890. - **Live Preview** with GitHub styling
  891. - **Smart Import/Export** (MD, HTML, PDF)
  892. - **Mermaid Diagrams** for visual documentation
  893. - **LaTeX Math Support** for scientific notation
  894. - **Emoji Support** 😄 👍 🎉
  895. ## 💻 Code with Syntax Highlighting
  896. ```javascript
  897. function renderMarkdown() {
  898. const markdown = markdownEditor.value;
  899. const html = marked.parse(markdown);
  900. const sanitizedHtml = DOMPurify.sanitize(html);
  901. markdownPreview.innerHTML = sanitizedHtml;
  902. // Syntax highlighting is handled automatically
  903. // during the parsing phase by the marked renderer.
  904. // Themes are applied instantly via CSS variables.
  905. }
  906. ```
  907. ## 🧮 Mathematical Expressions
  908. Write complex formulas with LaTeX syntax:
  909. Inline equation: $$E = mc^2$$
  910. Display equations:
  911. $$\frac{\partial f}{\partial x} = \lim_{h \to 0} \frac{f(x+h) - f(x)}{h}$$
  912. $$\sum_{i=1}^{n} i^2 = \frac{n(n+1)(2n+1)}{6}$$
  913. ## 📊 Mermaid Diagrams
  914. Create powerful visualizations directly in markdown:
  915. ```mermaid
  916. flowchart LR
  917. A[Start] --> B{Is it working?}
  918. B -->|Yes| C[Great!]
  919. B -->|No| D[Debug]
  920. C --> E[Deploy]
  921. D --> B
  922. ```
  923. ### Sequence Diagram Example
  924. ```mermaid
  925. sequenceDiagram
  926. User->>Editor: Type markdown
  927. Editor->>Preview: Render content
  928. User->>Editor: Make changes
  929. Editor->>Preview: Update rendering
  930. User->>Export: Save as PDF
  931. ```
  932. ## 📋 Task Management
  933. - [x] Create responsive layout
  934. - [x] Implement live preview with GitHub styling
  935. - [x] Add syntax highlighting for code blocks
  936. - [x] Support math expressions with LaTeX
  937. - [x] Enable mermaid diagrams
  938. ## 🆚 Feature Comparison
  939. | Feature | Markdown ++ (Ours) | Other Markdown Editors |
  940. |:-------------------------|:----------------------:|:-----------------------:|
  941. | Live Preview | ✅ GitHub-Styled | ✅ |
  942. | Sync Scrolling | ✅ Two-way | 🔄 Partial/None |
  943. | Mermaid Support | ✅ | ❌/Limited |
  944. | LaTeX Math Rendering | ✅ | ❌/Limited |
  945. ### 📝 Multi-row Headers Support
  946. <table>
  947. <thead>
  948. <tr>
  949. <th rowspan="2">Document Type</th>
  950. <th colspan="2">Support</th>
  951. </tr>
  952. <tr>
  953. <th>Markdown ++ (Ours)</th>
  954. <th>Other Markdown Editors</th>
  955. </tr>
  956. </thead>
  957. <tbody>
  958. <tr>
  959. <td>Technical Docs</td>
  960. <td>Full + Diagrams</td>
  961. <td>Limited/Basic</td>
  962. </tr>
  963. <tr>
  964. <td>Research Notes</td>
  965. <td>Full + Math</td>
  966. <td>Partial</td>
  967. </tr>
  968. <tr>
  969. <td>Developer Guides</td>
  970. <td>Full + Export Options</td>
  971. <td>Basic</td>
  972. </tr>
  973. </tbody>
  974. </table>
  975. ## 📝 Text Formatting Examples
  976. ### Text Formatting
  977. Text can be formatted in various ways for ~~strikethrough~~, **bold**, *italic*, or ***bold italic***.
  978. For highlighting important information, use <mark>highlighted text</mark> or add <u>underlines</u> where appropriate.
  979. ### Superscript and Subscript
  980. Chemical formulas: H<sub>2</sub>O, CO<sub>2</sub>
  981. Mathematical notation: x<sup>2</sup>, e<sup>iπ</sup>
  982. ### Keyboard Keys
  983. Press <kbd>Ctrl</kbd> + <kbd>B</kbd> for bold text.
  984. ### Abbreviations
  985. <abbr title="Graphical User Interface">GUI</abbr>
  986. <abbr title="Application Programming Interface">API</abbr>
  987. ### Text Alignment
  988. <div style="text-align: center">
  989. Centered text for headings or important notices
  990. </div>
  991. <div style="text-align: right">
  992. Right-aligned text (for dates, signatures, etc.)
  993. </div>
  994. ### **Lists**
  995. Create bullet points:
  996. * Item 1
  997. * Item 2
  998. * Nested item
  999. * Nested further
  1000. ### **Links and Images**
  1001. Add a [link](https://git.4parv.in/parv.ashwani/markdownplusplus) to important resources.
  1002. Embed an image:
  1003. <img alt="Markdown Logo" src="https://markdownplusplus.pages.dev/assets/icon.jpg" width="120" height="120">
  1004. ### **Blockquotes**
  1005. Quote someone famous:
  1006. > "The best way to predict the future is to invent it." - Alan Kay
  1007. ---
  1008. ## 🛡️ Security Note
  1009. This is a fully client-side application. Your content never leaves your browser and stays secure on your device.
  1010. </script>
  1011. <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
  1012. <script src="script.js"></script>
  1013. <!-- Screen reader dynamic accessibility announcer -->
  1014. <div id="app-accessibility-announcer" class="visually-hidden" aria-live="polite" aria-atomic="true"></div>
  1015. </body>
  1016. </html>