Merge branch 'master' of https://github.com/naturalcrit/homebrewery into fix-codemirror

This commit is contained in:
Víctor Losada Hernández
2026-09-25 19:21:31 +02:00
46 changed files with 1926 additions and 3363 deletions
+41 -7
View File
@@ -1,4 +1,4 @@
/* eslint max-lines: ["error", { "max": 405 }] */
/* eslint max-lines: ["error", { "max": 455 }] */
import './codeEditor.less';
import React, { useEffect, useRef, forwardRef, useImperativeHandle } from 'react';
@@ -42,6 +42,7 @@ import cm5Themes from 'codemirror-5-themes';
const themes = { default: defaultCM5Theme, ...cm5Themes, darkbrewery };
const themeCompartment = new Compartment();
const highlightCompartment = new Compartment();
const settingsCompartment = new Compartment();
import { generalKeymap, markdownKeymap, cssKeymap, formatCSS } from './extensions/customKeyMaps.js';
import foldOnPages from './extensions/customFolding.js';
@@ -78,6 +79,20 @@ const programmaticCursorLineField = StateField.define({
provide : (decorationSet)=>EditorView.decorations.from(decorationSet)
});
const createSettingsExtensions = (settings)=>[
...(settings.autoCloseBrackets ? [autoCloseBrackets] : []),
...(settings.lineNumbers ? [lineNumbers()] : []),
...(settings.activeLineShading ? [highlightActiveLine(),
highlightActiveLineGutter()] : []),
...(settings.fontSize
? [EditorView.theme({
'&, .cm-content' : {
fontSize : `${settings.fontSize || 1}em`,
},
})]
: []),
];
const CodeEditor = forwardRef(
(
{
@@ -88,9 +103,11 @@ const CodeEditor = forwardRef(
onChange = ()=>{},
onCursorChange = ()=>{},
onViewChange = ()=>{},
onThemeChange = ()=>{},
editorTheme = 'default',
style,
renderer,
settings = {},
...props
},
ref,
@@ -163,8 +180,7 @@ const CodeEditor = forwardRef(
EditorView.lineWrapping,
setEventListeners,
languageExtension,
autoCloseBrackets,
lineNumbers(),
settingsCompartment.of(createSettingsExtensions(settings)),
scrollPastEnd(),
search(),
history(), //allows for undo and redo
@@ -178,10 +194,8 @@ const CodeEditor = forwardRef(
}),
//highlights
highlightCompartment.of([customHighlightPlugin(renderer, tab), highlightExtension]),
highlightCompartment.of([customHighlightPlugin(renderer, tab, settings), highlightExtension]),
themeCompartment.of(themeExtension),
highlightActiveLine(),
highlightActiveLineGutter(),
//keyboard shortcut
keymap.of([...defaultKeymap, foldKeymap, ...searchKeymap]),
@@ -271,6 +285,12 @@ const CodeEditor = forwardRef(
}
view.setState(nextState);
view.dispatch({
effects : settingsCompartment.reconfigure(
createSettingsExtensions(settings)
),
});
restoreFolds(view, foldsRef.current[tab]);
const savedScroll = scrollRef.current[tab];
@@ -308,6 +328,9 @@ const CodeEditor = forwardRef(
view.dispatch({
effects : themeCompartment.reconfigure(themeExtension),
});
const isDark = view.state.facet(EditorView.darkTheme);
onThemeChange(isDark);
}, [editorTheme, tab]);
useEffect(()=>{
@@ -320,10 +343,21 @@ const CodeEditor = forwardRef(
: syntaxHighlighting(legacyCustomHighlightStyle);
view.dispatch({
effects : highlightCompartment.reconfigure([customHighlightPlugin(renderer, tab), highlightExtension]),
effects : highlightCompartment.reconfigure([customHighlightPlugin(renderer, tab, settings), highlightExtension])
});
}, [renderer, tab]);
useEffect(()=>{
const view = viewRef.current;
if(!view) return;
view.dispatch({
effects : settingsCompartment.reconfigure(
createSettingsExtensions(settings)
),
});
}, [settings]);
useImperativeHandle(ref, ()=>({
injectText : (text)=>{
@@ -366,7 +366,7 @@ class ImageWidget extends WidgetType {
}
}
export function customHighlightPlugin(renderer, tab) {
export function customHighlightPlugin(renderer, tab, settings) {
//this function takes the custom tokens created in the tokenize function in customhighlight files
//takes the tokens defined by that function and assigns classes to them
//it also creates page number and snippet number widgets
@@ -398,7 +398,7 @@ export function customHighlightPlugin(renderer, tab) {
const tree = ensureSyntaxTree(view.state, view.state.doc.length, 50) || syntaxTree(view.state);
tree.iterate({
enter : (node)=>{
if(node.name === 'Image') {
if(node.name === 'Image' && settings.showImagePreviews) {
const url = getUrl(node, view.state.doc);
const widgetPosition = node.node.lastChild.from;
@@ -431,7 +431,7 @@ export function customHighlightPlugin(renderer, tab) {
const to = line.from + token.to;
const attrs = {};
if(token.type === 'Image' && token.url) {
if(token.type === 'Image' && token.url && settings.showImagePreviews) {
attrs['data-url'] = token.url;
}
+2
View File
@@ -7,6 +7,7 @@ const Combobox = createReactClass({
displayName : 'Combobox',
getDefaultProps : function() {
return {
id : '',
className : '',
trigger : 'hover',
default : '',
@@ -75,6 +76,7 @@ const Combobox = createReactClass({
onClick= {this.props.trigger == 'click' ? ()=>{this.handleDropdown(true);} : undefined}
{...(this.props.tooltip ? { 'data-tooltip-right': this.props.tooltip } : {})}>
<input
id={this.props.id}
type='text'
onChange={(e)=>this.handleInput(e)}
value={this.state.value || ''}
+3 -4
View File
@@ -4,7 +4,7 @@
.item i {
position : absolute;
right : 10px;
color : black;
color : inherit;
}
.dropdown-options {
position : absolute;
@@ -32,14 +32,13 @@
font-size : 11px;
cursor : default;
&:hover {
background-color : rgb(163, 163, 163);
filter : brightness(120%);
background-color : #ddd;
}
.detail {
width : 100%;
font-size : 9px;
font-style : italic;
color : rgb(124, 124, 124);
color : #7c7c7c;
text-align : left;
}
}
+5 -1
View File
@@ -7,7 +7,7 @@
@property --activeTriggerColor {
syntax: '<color>';
inherits: true;
initial-value: #DDD;
initial-value: #999;
}
:root{
@@ -30,4 +30,8 @@
}
.menu-wrapper:has(:popover-open) > button { // if menu is open...
background-color: var(--activeTriggerColor, hsl(from var(--menuColor) h s calc(l * .85))); // tint menu triggers based on menu color
}
.darkMode .menu-wrapper:has(:popover-open) > button { // if menu is open...
--activeTriggerColor : #444; // tint menu triggers based on menu color
}