mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-09-20 12:22:59 +00:00
Merge branch 'master' of https://github.com/naturalcrit/homebrewery into add-settings-editor
This commit is contained in:
@@ -44,9 +44,9 @@ const themeCompartment = new Compartment();
|
||||
const highlightCompartment = new Compartment();
|
||||
const settingsCompartment = new Compartment();
|
||||
|
||||
import { generalKeymap, markdownKeymap } from './extensions/customKeyMaps.js';
|
||||
import { generalKeymap, markdownKeymap, cssKeymap, formatCSS } from './extensions/customKeyMaps.js';
|
||||
import foldOnPages from './extensions/customFolding.js';
|
||||
import { customHighlightPlugin, customHighlightStyle } from './extensions/customHighlight.js';
|
||||
import { customHighlightStyle , customHighlightPlugin } from './extensions/customHighlight.js';
|
||||
import { legacyCustomHighlightStyle } from './extensions/legacyCustomHighlight.js';
|
||||
|
||||
const PAGEBREAK_REGEX_V3 = /^(?=\\page(?:break)?(?: *{[^\n{}]*})?$)/m;
|
||||
@@ -199,7 +199,7 @@ const CodeEditor = forwardRef(
|
||||
//keyboard shortcut
|
||||
keymap.of([...defaultKeymap, foldKeymap, ...searchKeymap]),
|
||||
generalKeymap,
|
||||
...(tab !== 'brewStyles' ? [markdownKeymap] : []),
|
||||
...(tab === 'brewStyles' ? [cssKeymap] : [markdownKeymap]),
|
||||
|
||||
//multiple cursors and selections
|
||||
drawSelection(),
|
||||
@@ -386,6 +386,8 @@ const CodeEditor = forwardRef(
|
||||
}, 400);
|
||||
},
|
||||
|
||||
formatCode : ()=>formatCSS(viewRef.current),
|
||||
|
||||
undo : ()=>undo(viewRef.current),
|
||||
redo : ()=>redo(viewRef.current),
|
||||
|
||||
|
||||
@@ -15,6 +15,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideacross {
|
||||
0% {
|
||||
bottom: -200px;
|
||||
left: -200px;
|
||||
}
|
||||
|
||||
100% {
|
||||
bottom:100%;
|
||||
left:100%;
|
||||
}
|
||||
}
|
||||
|
||||
:where(.codeEditor) {
|
||||
width : 100%;
|
||||
height : calc(100% - 25px);
|
||||
@@ -23,6 +35,27 @@
|
||||
.cm-editor {
|
||||
height : 100%;
|
||||
outline : none !important;
|
||||
|
||||
&.cm-flash {
|
||||
position:relative;
|
||||
&::after {
|
||||
position:absolute;
|
||||
content:'';
|
||||
bottom:-200px;
|
||||
left:-200px;
|
||||
translate:-50%;
|
||||
width:200%;
|
||||
height:100px;
|
||||
background:linear-gradient(0deg, #89eafc00 0px, #89ebfc8e 50px, #89eafc00 100px, transparent);
|
||||
display:block;
|
||||
|
||||
rotate:30deg;
|
||||
|
||||
@media screen and (prefers-reduced-motion: no-preference) {
|
||||
animation: .5s linear 1 slideacross ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.brewSnippets .cm-snippetLine,
|
||||
|
||||
@@ -3,7 +3,60 @@ import { keymap } from '@codemirror/view';
|
||||
import { undo, redo, indentMore, indentLess, deleteLine } from '@codemirror/commands';
|
||||
import { EditorSelection } from '@codemirror/state';
|
||||
import { Prec } from '@codemirror/state';
|
||||
import * as prettier from 'prettier/standalone';
|
||||
import * as postcssPlugin from 'prettier/plugins/postcss';
|
||||
|
||||
export async function formatCSS(view) {
|
||||
try {
|
||||
const { from, to, empty } = view.state.selection.main;
|
||||
const fullDoc = view.state.doc.toString();
|
||||
const selection = view.state.doc.sliceString(from, to);
|
||||
const code = empty ? fullDoc : selection;
|
||||
|
||||
let formatted = await prettier.format(code, {
|
||||
parser: 'css',
|
||||
plugins: [postcssPlugin],
|
||||
|
||||
// formatting options
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
printWidth: 100,
|
||||
singleQuote: false,
|
||||
trailingComma: 'all',
|
||||
bracketSpacing: true,
|
||||
endOfLine: 'lf'
|
||||
});
|
||||
|
||||
//format manually single declaration rules to span one line.
|
||||
//Prettier can't do it by default, this is crude but it works
|
||||
formatted = formatted.replace(
|
||||
/([^{]+)\{\s*\n\s*([^;\n]+:[^;\n]+;)\s*\n\s*\}(\s*)/g,
|
||||
(_, selector, decl, whitespace) =>
|
||||
`${selector} { ${decl.trim()} }${whitespace}`
|
||||
);
|
||||
if(formatted === code) return true;
|
||||
|
||||
const dom = view.dom;
|
||||
dom.classList.add('cm-flash');
|
||||
|
||||
setTimeout(()=>{
|
||||
dom.classList.remove('cm-flash');
|
||||
|
||||
view.dispatch({
|
||||
changes : {
|
||||
from : empty ? 0 : from,
|
||||
to : empty ? view.state.doc.length : to,
|
||||
insert : formatted
|
||||
}
|
||||
});
|
||||
|
||||
}, 500);
|
||||
} catch (err) {
|
||||
console.error('Error formatting css: ', err);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
const insertTab = (view)=>{
|
||||
// If any selection spans multiple lines, delegates to CodeMirror's indentMore
|
||||
// Otherwise inserts two spaces at each cursor/selection
|
||||
@@ -188,6 +241,11 @@ export const generalKeymap = Prec.high(keymap.of([
|
||||
{ key: 'Mod-d', run: deleteLine }, //annoyingly overrides "selectNextOccurrence" because users asked
|
||||
]));
|
||||
|
||||
export const cssKeymap = Prec.highest(keymap.of([
|
||||
{ key: 'Mod-Shift-f', run: formatCSS },
|
||||
{ key: 'Alt-Shift-f', run: formatCSS },
|
||||
]));
|
||||
|
||||
export const markdownKeymap = Prec.highest(keymap.of([
|
||||
|
||||
{ key: 'Mod-b', run: wrapSelection('**', '**') }, // makeBold
|
||||
|
||||
@@ -138,6 +138,10 @@ const Editor = forwardRef(
|
||||
useEffect(()=>{ if(liveScroll) brewJump(currentEditorViewPageNum, false); }, [currentEditorViewPageNum, liveScroll]);
|
||||
useEffect(()=>{ if(liveScroll) brewJump(currentEditorCursorPageNum, false); }, [currentEditorCursorPageNum, liveScroll]);
|
||||
|
||||
const handleFormatCode = () => {
|
||||
codeEditor.current?.formatCode();
|
||||
};
|
||||
|
||||
const handleControlKeys = (e)=>{
|
||||
if(!(e.ctrlKey && e.metaKey && e.shiftKey)) return;
|
||||
const LEFTARROW_KEY = 37;
|
||||
@@ -371,6 +375,7 @@ const Editor = forwardRef(
|
||||
redo={redo}
|
||||
foldCode={foldCode}
|
||||
unfoldCode={unfoldCode}
|
||||
formatCode={isStyle() ? handleFormatCode : null}
|
||||
historySize={historySize()}
|
||||
currentEditorTheme={editorSettings.editorTheme}
|
||||
updateEditorTheme={updateEditorTheme}
|
||||
|
||||
@@ -35,21 +35,22 @@ const Snippetbar = createReactClass({
|
||||
displayName : 'SnippetBar',
|
||||
getDefaultProps : function() {
|
||||
return {
|
||||
brew : {},
|
||||
view : 'text',
|
||||
onViewChange : ()=>{},
|
||||
onInject : ()=>{},
|
||||
onToggle : ()=>{},
|
||||
showEditButtons : true,
|
||||
renderer : 'legacy',
|
||||
undo : ()=>{},
|
||||
redo : ()=>{},
|
||||
historySize : ()=>{},
|
||||
foldCode : ()=>{},
|
||||
unfoldCode : ()=>{},
|
||||
cursorPos : {},
|
||||
themeBundle : [],
|
||||
updateBrew : ()=>{}
|
||||
brew : {},
|
||||
view : 'text',
|
||||
onViewChange : ()=>{},
|
||||
onInject : ()=>{},
|
||||
onToggle : ()=>{},
|
||||
showEditButtons : true,
|
||||
renderer : 'legacy',
|
||||
undo : ()=>{},
|
||||
redo : ()=>{},
|
||||
historySize : ()=>{},
|
||||
foldCode : ()=>{},
|
||||
unfoldCode : ()=>{},
|
||||
formatCode : ()=>{},
|
||||
cursorPos : {},
|
||||
themeBundle : [],
|
||||
updateBrew : ()=>{}
|
||||
};
|
||||
},
|
||||
|
||||
@@ -223,6 +224,11 @@ const Snippetbar = createReactClass({
|
||||
onClick={this.props.unfoldCode} >
|
||||
<i className='fas fa-expand-alt' />
|
||||
</div>
|
||||
<div className={`editorTheme ${this.state.themeSelector ? 'active' : ''}`}
|
||||
onClick={this.toggleThemeSelector} >
|
||||
<i className='fas fa-palette' />
|
||||
{this.state.themeSelector && this.renderThemeSelector()}
|
||||
</div>
|
||||
</div></>}
|
||||
|
||||
<div className='tabs'>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
display : flex;
|
||||
justify-content : flex-end;
|
||||
min-width : 275px; //must be controlled every time an item is added, must be hardcoded for the wrapping as it is applied
|
||||
font-size : 0.85rem;
|
||||
font-size: .85rem;
|
||||
&:only-child {min-width : unset; margin-left : auto;}
|
||||
|
||||
>div {
|
||||
@@ -75,6 +75,11 @@
|
||||
color : grey;
|
||||
&.active { color : inherit; }
|
||||
}
|
||||
&.formatCode {
|
||||
.tooltipLeft('Clean your Code');
|
||||
color : grey;
|
||||
&.active { color : inherit; }
|
||||
}
|
||||
&.history {
|
||||
.tooltipLeft('History');
|
||||
position : relative;
|
||||
@@ -203,7 +208,7 @@
|
||||
}
|
||||
}
|
||||
@container editor (width < 841px) {
|
||||
.snippetBar {
|
||||
.snippetBar {
|
||||
.editors {
|
||||
flex : 1;
|
||||
justify-content : space-between;
|
||||
@@ -216,4 +221,3 @@
|
||||
.editors > div.history > .dropdown { right : unset; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Generated
+3880
-2081
File diff suppressed because it is too large
Load Diff
@@ -144,6 +144,7 @@
|
||||
"nanoid": "6.0.1",
|
||||
"nconf": "^0.13.0",
|
||||
"node": "^26.7.0",
|
||||
"prettier": "^3.8.1",
|
||||
"react": "^19.2.7",
|
||||
"react-dom": "^19.2.7",
|
||||
"react-frame-component": "^5.3.2",
|
||||
|
||||
Reference in New Issue
Block a user