mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-25 22:43:03 +00:00
93 lines
2.8 KiB
JavaScript
93 lines
2.8 KiB
JavaScript
const React = require('react');
|
|
const ReactDOM = require('react-dom');
|
|
const { PATTERNS, FIELD_TYPE } = require('./widget-elements/constants');
|
|
require('./widget-elements/hints/hints.jsx');
|
|
|
|
module.exports = function(CodeMirror, widgets, cm, setHints) {
|
|
const hintsEl = document.createElement('ul');
|
|
hintsEl.id = 'hints';
|
|
hintsEl.role = 'listbox';
|
|
hintsEl.ariaExpanded = 'true';
|
|
hintsEl.className = 'CodeMirror-hints default';
|
|
hintsEl.style = 'display: none;';
|
|
document.body.append(hintsEl);
|
|
|
|
const { cClass, field } = require('./widget-elements')(CodeMirror, setHints);
|
|
const widgetOptions = widgets.map((widget)=>({
|
|
name : widget.name,
|
|
pattern : PATTERNS.widget[widget.type](widget.name),
|
|
createWidget : (n, node)=>{
|
|
const parent = document.createElement('div');
|
|
const classes = (widget.classes || []).map((c, i)=>cClass(cm, n, `{{${widget.name}`, c));
|
|
const fieldNames = (widget.fields || []).map((f)=>f.name);
|
|
const fields = (widget.fields || []).map((f, i)=>field(cm, n, f)).filter((f)=>!!f);
|
|
const { text } = cm.lineInfo(n);
|
|
const styles = [...text.matchAll(PATTERNS.collectStyles)].map(([_, style])=>{
|
|
if(fieldNames.includes(style)) return false;
|
|
return field(cm, n, {
|
|
name : style,
|
|
type : FIELD_TYPE.STYLE,
|
|
increment : 5
|
|
});
|
|
}).filter((s)=>!!s);
|
|
|
|
ReactDOM.render(<React.Fragment>
|
|
{classes}
|
|
{fields}
|
|
{styles}
|
|
</React.Fragment>, node || parent);
|
|
|
|
return node || parent;
|
|
}
|
|
}));
|
|
|
|
const updateLineWidgets = (n, remove)=>{
|
|
const { text, widgets } = cm.lineInfo(n);
|
|
const widgetOption = widgetOptions.find((option)=>!!text.match(option.pattern));
|
|
if(!widgetOption) return;
|
|
if(!!widgets) {
|
|
for (const widget of widgets) {
|
|
widgetOption.createWidget(n, widget.node);
|
|
}
|
|
} else {
|
|
return cm.addLineWidget(n, widgetOption.createWidget(n), {
|
|
above : false,
|
|
coverGutter : false,
|
|
noHScroll : true,
|
|
className : `snippet-options-widget ${widgetOption.name}-widget ${widgetOption.name}-widget-${n}`
|
|
});
|
|
}
|
|
};
|
|
|
|
return {
|
|
removeLineWidgets : (widget)=>{
|
|
cm.removeLineWidget(widget);
|
|
},
|
|
updateLineWidgets,
|
|
updateAllLineWidgets : ()=>{
|
|
for (let i = 0; i < cm.lineCount(); i++) {
|
|
const { widgets } = cm.lineInfo(i);
|
|
if(!!widgets) {
|
|
updateLineWidgets(i);
|
|
}
|
|
}
|
|
},
|
|
updateWidgetGutter : ()=>{
|
|
cm.operation(()=>{
|
|
for (let i = 0; i < cm.lineCount(); i++) {
|
|
const line = cm.getLine(i);
|
|
|
|
if(widgetOptions.some((option)=>line.match(option.pattern))) {
|
|
const optionsMarker = document.createElement('div');
|
|
optionsMarker.style.color = '#822';
|
|
optionsMarker.style.cursor = 'pointer';
|
|
optionsMarker.innerHTML = '●';
|
|
cm.setGutterMarker(i, 'widget-gutter', optionsMarker);
|
|
} else {
|
|
cm.setGutterMarker(i, 'widget-gutter', null);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}; |