213 lines
10 KiB
HTML
213 lines
10 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<!-- CSP: script-src 只允许 self,阻断内联脚本执行 -->
|
||
<!-- style-src 保留 unsafe-inline:highlight.js 代码高亮依赖 CSS class,
|
||
但已通过 sanitizeHTML 移除恶意 style 属性和 expression() -->
|
||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; form-action 'self';">
|
||
<title>MarkLite</title>
|
||
<link rel="stylesheet" href="style.css">
|
||
<link rel="stylesheet" href="../lib/highlight-github.css">
|
||
</head>
|
||
<body>
|
||
<div id="app">
|
||
<!-- Toolbar -->
|
||
<div id="toolbar">
|
||
<div class="toolbar-left">
|
||
<button id="btn-open" class="toolbar-btn" title="打开文件 (Ctrl+O)">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
|
||
</svg>
|
||
<span>打开</span>
|
||
</button>
|
||
<button id="btn-save" class="toolbar-btn" title="保存文件 (Ctrl+S)">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path>
|
||
<polyline points="17 21 17 13 7 13 7 21"></polyline>
|
||
<polyline points="7 3 7 8 15 8"></polyline>
|
||
</svg>
|
||
<span>保存</span>
|
||
</button>
|
||
<div class="toolbar-divider"></div>
|
||
<button id="btn-split" class="toolbar-btn active" title="编辑+预览 (Ctrl+1)">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
||
<line x1="12" y1="3" x2="12" y2="21"></line>
|
||
</svg>
|
||
<span>分屏</span>
|
||
</button>
|
||
<button id="btn-editor" class="toolbar-btn" title="纯编辑 (Ctrl+2)">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
|
||
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
|
||
</svg>
|
||
<span>编辑</span>
|
||
</button>
|
||
<button id="btn-preview" class="toolbar-btn" title="纯预览 (Ctrl+3)">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
|
||
<circle cx="12" cy="12" r="3"></circle>
|
||
</svg>
|
||
<span>预览</span>
|
||
</button>
|
||
</div>
|
||
<div class="toolbar-right">
|
||
<button id="btn-dark" class="toolbar-btn" title="切换暗色主题">
|
||
<svg id="icon-dark" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
||
</svg>
|
||
<svg id="icon-light" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display:none">
|
||
<circle cx="12" cy="12" r="5"></circle>
|
||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tab bar -->
|
||
<div id="tab-bar">
|
||
<div id="tab-list"></div>
|
||
<button id="btn-new-tab" class="tab-add-btn" title="新建标签页 (Ctrl+T)">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<line x1="12" y1="5" x2="12" y2="19"></line>
|
||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- External modification banner -->
|
||
<div id="modified-banner" class="hidden">
|
||
<span>文件已被外部程序修改</span>
|
||
<button id="btn-reload" class="banner-btn">重新加载</button>
|
||
<button id="btn-dismiss" class="banner-btn">忽略</button>
|
||
</div>
|
||
|
||
<!-- Sidebar -->
|
||
<div id="sidebar">
|
||
<div id="sidebar-header">
|
||
<span id="sidebar-title">资源管理器</span>
|
||
<button id="btn-open-folder" class="sidebar-header-btn" title="打开文件夹">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<div id="sidebar-tree"></div>
|
||
</div>
|
||
|
||
<!-- Main content area -->
|
||
<div id="main-content">
|
||
<!-- Editor panel -->
|
||
<div id="editor-panel">
|
||
<!-- Search & Replace Bar -->
|
||
<div id="search-bar" class="hidden">
|
||
<div class="search-row">
|
||
<input type="text" id="search-input" placeholder="查找..." />
|
||
<span id="search-count"></span>
|
||
<button id="btn-case" class="search-opt-btn" title="区分大小写 (Alt+C)">Aa</button>
|
||
<button id="btn-regex" class="search-opt-btn" title="正则表达式 (Alt+R)">.*</button>
|
||
<button id="btn-prev" class="search-nav-btn" title="上一个 (Shift+Enter)">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="18 15 12 9 6 15"></polyline></svg>
|
||
</button>
|
||
<button id="btn-next" class="search-nav-btn" title="下一个 (Enter)">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"></polyline></svg>
|
||
</button>
|
||
<button id="btn-search-close" class="search-nav-btn" title="关闭 (Escape)">✕</button>
|
||
</div>
|
||
<div id="replace-row" class="hidden">
|
||
<input type="text" id="replace-input" placeholder="替换..." />
|
||
<button id="btn-replace" class="replace-btn" title="替换 (Ctrl+Shift+G)">替换</button>
|
||
<button id="btn-replace-all" class="replace-btn" title="全部替换 (Ctrl+Shift+H)">全部</button>
|
||
</div>
|
||
</div>
|
||
<div id="editor-wrapper">
|
||
<div id="line-numbers"></div>
|
||
<textarea id="editor" spellcheck="false" placeholder="在此输入 Markdown 内容,或拖拽 .md 文件到窗口打开..."></textarea>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Resizer -->
|
||
<div id="resizer"></div>
|
||
|
||
<!-- Preview panel -->
|
||
<div id="preview-panel">
|
||
<div id="preview" class="markdown-body"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Status bar -->
|
||
<div id="statusbar">
|
||
<div class="status-left">
|
||
<span id="status-text">就绪</span>
|
||
</div>
|
||
<div class="status-right">
|
||
<span id="status-encoding">UTF-8</span>
|
||
<span class="status-divider">|</span>
|
||
<span id="status-lang">Markdown</span>
|
||
<span class="status-divider">|</span>
|
||
<span id="status-size"></span>
|
||
<span class="status-divider status-size-divider">|</span>
|
||
<span id="status-cursor">行 1, 列 1</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Drop overlay -->
|
||
<div id="drop-overlay" class="hidden">
|
||
<div class="drop-content">
|
||
<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
|
||
</svg>
|
||
<p>释放文件以打开</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Welcome screen -->
|
||
<div id="welcome-screen">
|
||
<div class="welcome-content">
|
||
<div class="welcome-icon">
|
||
<svg width="80" height="80" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<rect x="10" y="5" width="80" height="90" rx="8" fill="#f0f6ff" stroke="#1a73e8" stroke-width="2"/>
|
||
<text x="50" y="45" text-anchor="middle" fill="#1a73e8" font-family="system-ui" font-weight="bold" font-size="32">M↓</text>
|
||
<text x="50" y="70" text-anchor="middle" fill="#5f6368" font-family="system-ui" font-size="12">MarkLite</text>
|
||
</svg>
|
||
</div>
|
||
<h1>欢迎使用 MarkLite</h1>
|
||
<p>一款轻量级的 Markdown 阅读器</p>
|
||
<div class="welcome-actions">
|
||
<button id="btn-welcome-open" class="welcome-btn primary">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
|
||
</svg>
|
||
打开文件
|
||
</button>
|
||
<button id="btn-welcome-new" class="welcome-btn secondary">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<line x1="12" y1="5" x2="12" y2="19"></line>
|
||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||
</svg>
|
||
新建文件
|
||
</button>
|
||
</div>
|
||
<div class="welcome-tips">
|
||
<p>💡 提示:可以直接拖拽 .md 文件到窗口打开</p>
|
||
<p>⌨️ 快捷键:Ctrl+O 打开 | Ctrl+S 保存 | Ctrl+F 搜索 | Ctrl+H 替换 | Ctrl+1/2/3 视图 | Ctrl+T 标签</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="../lib/marked.min.js"></script>
|
||
<script src="../lib/highlight.min.js"></script>
|
||
<script src="renderer.js"></script>
|
||
</body>
|
||
</html>
|