mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-03-26 10:28:13 +00:00
this should fold
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
scrollPastEnd,
|
||||
Decoration,
|
||||
ViewPlugin,
|
||||
WidgetType,
|
||||
} from '@codemirror/view';
|
||||
import { EditorState, Compartment } from '@codemirror/state';
|
||||
import { foldGutter, foldKeymap, syntaxHighlighting, HighlightStyle } from '@codemirror/language';
|
||||
@@ -97,6 +98,59 @@ const customHighlightPlugin = ViewPlugin.fromClass(
|
||||
},
|
||||
);
|
||||
|
||||
// ######################### FOLDING ###############################
|
||||
|
||||
|
||||
import { foldService } from '@codemirror/language';
|
||||
|
||||
class FoldPreviewWidget extends WidgetType {
|
||||
constructor(text) {
|
||||
super();
|
||||
this.text = text;
|
||||
}
|
||||
toDOM() {
|
||||
console.log(this.text);
|
||||
const span = document.createElement('span');
|
||||
span.className = 'cm-fold-placeholder';
|
||||
span.textContent = this.text;
|
||||
return span;
|
||||
}
|
||||
}
|
||||
|
||||
const homebreweryFold = foldService.of((state, lineStart)=>{
|
||||
const doc = state.doc;
|
||||
const matcher = /^(?=\\page(?:break)?(?: *{[^\n{}]*})?$)/m;
|
||||
|
||||
const startLine = doc.lineAt(lineStart);
|
||||
const prevLineText = startLine.number > 1 ? doc.line(startLine.number - 1).text : '';
|
||||
|
||||
if(startLine.number > 1 && !matcher.test(prevLineText)) return null;
|
||||
|
||||
let endLine = startLine.number;
|
||||
while (endLine < doc.lines && !matcher.test(doc.line(endLine + 1).text)) {
|
||||
endLine++;
|
||||
}
|
||||
|
||||
if(endLine === startLine.number) return null;
|
||||
|
||||
let preview = '';
|
||||
for (let i = startLine.number; i <= endLine; i++) {
|
||||
const text = doc.line(i).text.trim();
|
||||
if(text.length > 0) {
|
||||
preview = text;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!preview) preview = `Lines ${startLine.number}-${endLine}`;
|
||||
|
||||
preview = preview.replace('{', '').trim();
|
||||
if(preview.length > 50) preview = `${preview.slice(0, 50)}...`;
|
||||
preview = `↤ ${preview} ↦`;
|
||||
|
||||
return { from: startLine.from, to: doc.line(endLine).to, placeholder: new FoldPreviewWidget(preview) };
|
||||
});
|
||||
|
||||
// ######################### COMPONENT #############################
|
||||
|
||||
const CodeEditor = forwardRef(
|
||||
@@ -174,6 +228,7 @@ const CodeEditor = forwardRef(
|
||||
keymap.of(foldKeymap),
|
||||
foldGutter(),
|
||||
lineNumbers(),
|
||||
homebreweryFold,
|
||||
|
||||
themeCompartment.of(themeExtension), // 👈 key line
|
||||
|
||||
|
||||
@@ -24,35 +24,6 @@
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
/* Line numbers and gutters */
|
||||
.cm-gutters {
|
||||
background-color: #f0f0f0;
|
||||
color: #555;
|
||||
border-right: 1px solid #ddd;
|
||||
}
|
||||
|
||||
/* Folding gutter */
|
||||
.cm-foldGutter {
|
||||
cursor: pointer;
|
||||
color: grey;
|
||||
font-weight: 600;
|
||||
transition: background 0.1s;
|
||||
|
||||
&:hover {
|
||||
background: #dddddd;
|
||||
}
|
||||
}
|
||||
|
||||
/* Active line */
|
||||
.cm-activeLine {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.cm-activeLineGutter {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
/* Flash animation for source moves */
|
||||
.sourceMoveFlash .cm-line {
|
||||
animation-name: sourceMoveAnimation;
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
export default {
|
||||
registerHomebreweryHelper : function(CodeMirror) {
|
||||
CodeMirror.registerHelper('fold', 'homebrewerycss', function(cm, start) {
|
||||
|
||||
// BRACE FOLDING
|
||||
const startMatcher = /\{[ \t]*$/;
|
||||
const endMatcher = /\}[ \t]*$/;
|
||||
const activeLine = cm.getLine(start.line);
|
||||
|
||||
|
||||
if(activeLine.match(startMatcher)) {
|
||||
const lastLineNo = cm.lastLine();
|
||||
let end = start.line + 1;
|
||||
let braceCount = 1;
|
||||
|
||||
while (end < lastLineNo) {
|
||||
const curLine = cm.getLine(end);
|
||||
if(curLine.match(startMatcher)) braceCount++;
|
||||
if(curLine.match(endMatcher)) braceCount--;
|
||||
if(braceCount == 0) break;
|
||||
++end;
|
||||
}
|
||||
|
||||
return {
|
||||
from : CodeMirror.Pos(start.line, 0),
|
||||
to : CodeMirror.Pos(end, cm.getLine(end).length)
|
||||
};
|
||||
}
|
||||
|
||||
// @import and data-url folding
|
||||
const importMatcher = /^@import.*?;/;
|
||||
const dataURLMatcher = /url\(.*?data\:.*\)/;
|
||||
|
||||
if(activeLine.match(importMatcher) || activeLine.match(dataURLMatcher)) {
|
||||
return {
|
||||
from : CodeMirror.Pos(start.line, 0),
|
||||
to : CodeMirror.Pos(start.line, activeLine.length)
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user