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) {
|
if (this.config.syntaxHighlight) {
|
||||||
textarea.classList.add('me-textarea-highlight');
|
textarea.classList.add('me-textarea-highlight');
|
||||||
}
|
}
|
||||||
|
if (highlightLayer && !this.config.syntaxHighlight) {
|
||||||
|
highlightLayer.hidden = true;
|
||||||
|
}
|
||||||
editorInner.appendChild(textarea);
|
editorInner.appendChild(textarea);
|
||||||
|
|
||||||
editorPane.appendChild(editorInner);
|
editorPane.appendChild(editorInner);
|
||||||
@@ -1329,12 +1332,13 @@ class MarkdownEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_doHighlight() {
|
_doHighlight() {
|
||||||
|
if (!this.highlightLayer || this.highlightLayer.hidden || this._mode === 'preview') return;
|
||||||
const text = this._value || '';
|
const text = this._value || '';
|
||||||
if (!text) { this.highlightLayer.innerHTML = ''; return; }
|
if (!text) { this.highlightLayer.innerHTML = ''; return; }
|
||||||
// 超过 50KB 跳过,避免大文档卡顿
|
|
||||||
if (text.length > 50000) { this.highlightLayer.innerHTML = escapeHTML(text) + '\n'; return; }
|
if (text.length > 50000) { this.highlightLayer.innerHTML = escapeHTML(text) + '\n'; return; }
|
||||||
|
|
||||||
let html = escapeHTML(text);
|
let html = escapeHTML(text);
|
||||||
|
this._positionHighlightLayer();
|
||||||
|
|
||||||
// 正则按优先级:先匹配更具体的模式,避免被泛模式吞掉
|
// 正则按优先级:先匹配更具体的模式,避免被泛模式吞掉
|
||||||
// 1. 图片(先于链接)
|
// 1. 图片(先于链接)
|
||||||
@@ -1370,13 +1374,27 @@ class MarkdownEditor {
|
|||||||
if (this.textarea) {
|
if (this.textarea) {
|
||||||
this.textarea.classList.toggle('me-textarea-highlight', this.config.syntaxHighlight);
|
this.textarea.classList.toggle('me-textarea-highlight', this.config.syntaxHighlight);
|
||||||
}
|
}
|
||||||
if (!this.config.syntaxHighlight && this.highlightLayer) {
|
if (this.highlightLayer) {
|
||||||
this.highlightLayer.innerHTML = '';
|
this.highlightLayer.hidden = !this.config.syntaxHighlight;
|
||||||
|
}
|
||||||
|
if (this.config.syntaxHighlight) {
|
||||||
|
this._positionHighlightLayer();
|
||||||
|
this._doHighlight();
|
||||||
}
|
}
|
||||||
if (this.config.syntaxHighlight) this._doHighlight();
|
|
||||||
return this;
|
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() {
|
_updateWordCount() {
|
||||||
if (!this.config.wordCount || !this.statusEl) return;
|
if (!this.config.wordCount || !this.statusEl) return;
|
||||||
const text = this._value || '';
|
const text = this._value || '';
|
||||||
|
|||||||
+4
-2
@@ -134,13 +134,15 @@ const generateCSS = () => {
|
|||||||
.me-editor-inner { display: flex; height: 100%; overflow: hidden; position: relative; }
|
.me-editor-inner { display: flex; height: 100%; overflow: hidden; position: relative; }
|
||||||
/* 语法高亮叠加层(v0.1.14) */
|
/* 语法高亮叠加层(v0.1.14) */
|
||||||
.me-highlight-layer {
|
.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;
|
padding: 16px 18px; margin: 0; border: 0; outline: 0; overflow: hidden;
|
||||||
font-family: var(--md-mono); font-size: 13.5px; line-height: 1.7;
|
font-family: var(--md-mono); font-size: 13.5px; line-height: 1.7;
|
||||||
white-space: pre-wrap; word-wrap: break-word;
|
white-space: pre-wrap; word-wrap: break-word;
|
||||||
pointer-events: none; background: transparent;
|
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-heading { color: var(--md-accent); font-weight: 700; }
|
||||||
.mh-bold { color: var(--md-text); font-weight: 700; }
|
.mh-bold { color: var(--md-text); font-weight: 700; }
|
||||||
.mh-italic { font-style: italic; }
|
.mh-italic { font-style: italic; }
|
||||||
|
|||||||
Reference in New Issue
Block a user