fix(core): robust syntax highlight — dynamic positioning, mode-aware, proper toggle
- _positionHighlightLayer(): set left offset dynamically from gutter width - Use hidden attribute instead of clearing innerHTML for toggle - Skip highlight in preview mode - Initialize highlightLayer hidden state on construction - Remove hardcoded left:36px CSS
This commit is contained in:
+22
-4
@@ -233,6 +233,9 @@ class MarkdownEditor {
|
||||
if (this.config.syntaxHighlight) {
|
||||
textarea.classList.add('me-textarea-highlight');
|
||||
}
|
||||
if (highlightLayer && !this.config.syntaxHighlight) {
|
||||
highlightLayer.hidden = true;
|
||||
}
|
||||
editorInner.appendChild(textarea);
|
||||
|
||||
editorPane.appendChild(editorInner);
|
||||
@@ -1329,12 +1332,13 @@ class MarkdownEditor {
|
||||
}
|
||||
|
||||
_doHighlight() {
|
||||
if (!this.highlightLayer || this.highlightLayer.hidden || this._mode === 'preview') return;
|
||||
const text = this._value || '';
|
||||
if (!text) { this.highlightLayer.innerHTML = ''; return; }
|
||||
// 超过 50KB 跳过,避免大文档卡顿
|
||||
if (text.length > 50000) { this.highlightLayer.innerHTML = escapeHTML(text) + '\n'; return; }
|
||||
|
||||
let html = escapeHTML(text);
|
||||
this._positionHighlightLayer();
|
||||
|
||||
// 正则按优先级:先匹配更具体的模式,避免被泛模式吞掉
|
||||
// 1. 图片(先于链接)
|
||||
@@ -1370,13 +1374,27 @@ class MarkdownEditor {
|
||||
if (this.textarea) {
|
||||
this.textarea.classList.toggle('me-textarea-highlight', this.config.syntaxHighlight);
|
||||
}
|
||||
if (!this.config.syntaxHighlight && this.highlightLayer) {
|
||||
this.highlightLayer.innerHTML = '';
|
||||
if (this.highlightLayer) {
|
||||
this.highlightLayer.hidden = !this.config.syntaxHighlight;
|
||||
}
|
||||
if (this.config.syntaxHighlight) {
|
||||
this._positionHighlightLayer();
|
||||
this._doHighlight();
|
||||
}
|
||||
if (this.config.syntaxHighlight) this._doHighlight();
|
||||
return this;
|
||||
}
|
||||
|
||||
_positionHighlightLayer() {
|
||||
if (!this.highlightLayer) return;
|
||||
// 动态设置左边距:有行号时对齐行号宽度,无行号时从 0 开始
|
||||
if (this.gutter && this.config.lineNumbers && this.gutter.style.display !== 'none') {
|
||||
const w = this.gutter.getBoundingClientRect().width;
|
||||
this.highlightLayer.style.left = w + 'px';
|
||||
} else {
|
||||
this.highlightLayer.style.left = '0';
|
||||
}
|
||||
}
|
||||
|
||||
_updateWordCount() {
|
||||
if (!this.config.wordCount || !this.statusEl) return;
|
||||
const text = this._value || '';
|
||||
|
||||
+4
-2
@@ -134,13 +134,15 @@ const generateCSS = () => {
|
||||
.me-editor-inner { display: flex; height: 100%; overflow: hidden; position: relative; }
|
||||
/* 语法高亮叠加层(v0.1.14) */
|
||||
.me-highlight-layer {
|
||||
position: absolute; top: 0; left: 36px; right: 0; bottom: 0;
|
||||
position: absolute; top: 0; right: 0; bottom: 0;
|
||||
padding: 16px 18px; margin: 0; border: 0; outline: 0; overflow: hidden;
|
||||
font-family: var(--md-mono); font-size: 13.5px; line-height: 1.7;
|
||||
white-space: pre-wrap; word-wrap: break-word;
|
||||
pointer-events: none; background: transparent;
|
||||
color: var(--md-text);
|
||||
color: var(--md-text); z-index: 0;
|
||||
}
|
||||
/* 隐藏高亮层(语法高亮关闭时) */
|
||||
.me-highlight-layer[hidden] { display: none; }
|
||||
.mh-heading { color: var(--md-accent); font-weight: 700; }
|
||||
.mh-bold { color: var(--md-text); font-weight: 700; }
|
||||
.mh-italic { font-style: italic; }
|
||||
|
||||
Reference in New Issue
Block a user