sqlui 0.1.68 → 0.1.69
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.release-version +1 -1
- data/app/views/sqlui.erb +126 -73
- data/client/resources/help.css +8 -0
- data/client/resources/sqlui.css +17 -8
- data/client/resources/sqlui.js +142 -820
- metadata +2 -2
data/client/resources/sqlui.js
CHANGED
@@ -9566,7 +9566,7 @@
|
|
9566
9566
|
}
|
9567
9567
|
});
|
9568
9568
|
}
|
9569
|
-
const baseTheme$1$
|
9569
|
+
const baseTheme$1$2 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
9570
9570
|
"&": {
|
9571
9571
|
position: "relative !important",
|
9572
9572
|
boxSizing: "border-box",
|
@@ -10921,7 +10921,7 @@
|
|
10921
10921
|
}
|
10922
10922
|
mountStyles() {
|
10923
10923
|
this.styleModules = this.state.facet(styleModule);
|
10924
|
-
StyleModule.mount(this.root, this.styleModules.concat(baseTheme$1$
|
10924
|
+
StyleModule.mount(this.root, this.styleModules.concat(baseTheme$1$2).reverse());
|
10925
10925
|
}
|
10926
10926
|
readMeasured() {
|
10927
10927
|
if (this.updateState == 2 /* UpdateState.Updating */)
|
@@ -12865,214 +12865,6 @@
|
|
12865
12865
|
const showTooltip = /*@__PURE__*/Facet.define({
|
12866
12866
|
enables: [tooltipPlugin, baseTheme$4]
|
12867
12867
|
});
|
12868
|
-
const showHoverTooltip = /*@__PURE__*/Facet.define();
|
12869
|
-
class HoverTooltipHost {
|
12870
|
-
constructor(view) {
|
12871
|
-
this.view = view;
|
12872
|
-
this.mounted = false;
|
12873
|
-
this.dom = document.createElement("div");
|
12874
|
-
this.dom.classList.add("cm-tooltip-hover");
|
12875
|
-
this.manager = new TooltipViewManager(view, showHoverTooltip, t => this.createHostedView(t));
|
12876
|
-
}
|
12877
|
-
// Needs to be static so that host tooltip instances always match
|
12878
|
-
static create(view) {
|
12879
|
-
return new HoverTooltipHost(view);
|
12880
|
-
}
|
12881
|
-
createHostedView(tooltip) {
|
12882
|
-
let hostedView = tooltip.create(this.view);
|
12883
|
-
hostedView.dom.classList.add("cm-tooltip-section");
|
12884
|
-
this.dom.appendChild(hostedView.dom);
|
12885
|
-
if (this.mounted && hostedView.mount)
|
12886
|
-
hostedView.mount(this.view);
|
12887
|
-
return hostedView;
|
12888
|
-
}
|
12889
|
-
mount(view) {
|
12890
|
-
for (let hostedView of this.manager.tooltipViews) {
|
12891
|
-
if (hostedView.mount)
|
12892
|
-
hostedView.mount(view);
|
12893
|
-
}
|
12894
|
-
this.mounted = true;
|
12895
|
-
}
|
12896
|
-
positioned(space) {
|
12897
|
-
for (let hostedView of this.manager.tooltipViews) {
|
12898
|
-
if (hostedView.positioned)
|
12899
|
-
hostedView.positioned(space);
|
12900
|
-
}
|
12901
|
-
}
|
12902
|
-
update(update) {
|
12903
|
-
this.manager.update(update);
|
12904
|
-
}
|
12905
|
-
}
|
12906
|
-
const showHoverTooltipHost = /*@__PURE__*/showTooltip.compute([showHoverTooltip], state => {
|
12907
|
-
let tooltips = state.facet(showHoverTooltip).filter(t => t);
|
12908
|
-
if (tooltips.length === 0)
|
12909
|
-
return null;
|
12910
|
-
return {
|
12911
|
-
pos: Math.min(...tooltips.map(t => t.pos)),
|
12912
|
-
end: Math.max(...tooltips.filter(t => t.end != null).map(t => t.end)),
|
12913
|
-
create: HoverTooltipHost.create,
|
12914
|
-
above: tooltips[0].above,
|
12915
|
-
arrow: tooltips.some(t => t.arrow),
|
12916
|
-
};
|
12917
|
-
});
|
12918
|
-
class HoverPlugin {
|
12919
|
-
constructor(view, source, field, setHover, hoverTime) {
|
12920
|
-
this.view = view;
|
12921
|
-
this.source = source;
|
12922
|
-
this.field = field;
|
12923
|
-
this.setHover = setHover;
|
12924
|
-
this.hoverTime = hoverTime;
|
12925
|
-
this.hoverTimeout = -1;
|
12926
|
-
this.restartTimeout = -1;
|
12927
|
-
this.pending = null;
|
12928
|
-
this.lastMove = { x: 0, y: 0, target: view.dom, time: 0 };
|
12929
|
-
this.checkHover = this.checkHover.bind(this);
|
12930
|
-
view.dom.addEventListener("mouseleave", this.mouseleave = this.mouseleave.bind(this));
|
12931
|
-
view.dom.addEventListener("mousemove", this.mousemove = this.mousemove.bind(this));
|
12932
|
-
}
|
12933
|
-
update() {
|
12934
|
-
if (this.pending) {
|
12935
|
-
this.pending = null;
|
12936
|
-
clearTimeout(this.restartTimeout);
|
12937
|
-
this.restartTimeout = setTimeout(() => this.startHover(), 20);
|
12938
|
-
}
|
12939
|
-
}
|
12940
|
-
get active() {
|
12941
|
-
return this.view.state.field(this.field);
|
12942
|
-
}
|
12943
|
-
checkHover() {
|
12944
|
-
this.hoverTimeout = -1;
|
12945
|
-
if (this.active)
|
12946
|
-
return;
|
12947
|
-
let hovered = Date.now() - this.lastMove.time;
|
12948
|
-
if (hovered < this.hoverTime)
|
12949
|
-
this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime - hovered);
|
12950
|
-
else
|
12951
|
-
this.startHover();
|
12952
|
-
}
|
12953
|
-
startHover() {
|
12954
|
-
clearTimeout(this.restartTimeout);
|
12955
|
-
let { lastMove } = this;
|
12956
|
-
let pos = this.view.contentDOM.contains(lastMove.target) ? this.view.posAtCoords(lastMove) : null;
|
12957
|
-
if (pos == null)
|
12958
|
-
return;
|
12959
|
-
let posCoords = this.view.coordsAtPos(pos);
|
12960
|
-
if (posCoords == null || lastMove.y < posCoords.top || lastMove.y > posCoords.bottom ||
|
12961
|
-
lastMove.x < posCoords.left - this.view.defaultCharacterWidth ||
|
12962
|
-
lastMove.x > posCoords.right + this.view.defaultCharacterWidth)
|
12963
|
-
return;
|
12964
|
-
let bidi = this.view.bidiSpans(this.view.state.doc.lineAt(pos)).find(s => s.from <= pos && s.to >= pos);
|
12965
|
-
let rtl = bidi && bidi.dir == Direction.RTL ? -1 : 1;
|
12966
|
-
let open = this.source(this.view, pos, (lastMove.x < posCoords.left ? -rtl : rtl));
|
12967
|
-
if (open === null || open === void 0 ? void 0 : open.then) {
|
12968
|
-
let pending = this.pending = { pos };
|
12969
|
-
open.then(result => {
|
12970
|
-
if (this.pending == pending) {
|
12971
|
-
this.pending = null;
|
12972
|
-
if (result)
|
12973
|
-
this.view.dispatch({ effects: this.setHover.of(result) });
|
12974
|
-
}
|
12975
|
-
}, e => logException(this.view.state, e, "hover tooltip"));
|
12976
|
-
}
|
12977
|
-
else if (open) {
|
12978
|
-
this.view.dispatch({ effects: this.setHover.of(open) });
|
12979
|
-
}
|
12980
|
-
}
|
12981
|
-
mousemove(event) {
|
12982
|
-
var _a;
|
12983
|
-
this.lastMove = { x: event.clientX, y: event.clientY, target: event.target, time: Date.now() };
|
12984
|
-
if (this.hoverTimeout < 0)
|
12985
|
-
this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime);
|
12986
|
-
let tooltip = this.active;
|
12987
|
-
if (tooltip && !isInTooltip(this.lastMove.target) || this.pending) {
|
12988
|
-
let { pos } = tooltip || this.pending, end = (_a = tooltip === null || tooltip === void 0 ? void 0 : tooltip.end) !== null && _a !== void 0 ? _a : pos;
|
12989
|
-
if ((pos == end ? this.view.posAtCoords(this.lastMove) != pos
|
12990
|
-
: !isOverRange(this.view, pos, end, event.clientX, event.clientY, 6 /* Hover.MaxDist */))) {
|
12991
|
-
this.view.dispatch({ effects: this.setHover.of(null) });
|
12992
|
-
this.pending = null;
|
12993
|
-
}
|
12994
|
-
}
|
12995
|
-
}
|
12996
|
-
mouseleave(e) {
|
12997
|
-
clearTimeout(this.hoverTimeout);
|
12998
|
-
this.hoverTimeout = -1;
|
12999
|
-
if (this.active && !isInTooltip(e.relatedTarget))
|
13000
|
-
this.view.dispatch({ effects: this.setHover.of(null) });
|
13001
|
-
}
|
13002
|
-
destroy() {
|
13003
|
-
clearTimeout(this.hoverTimeout);
|
13004
|
-
this.view.dom.removeEventListener("mouseleave", this.mouseleave);
|
13005
|
-
this.view.dom.removeEventListener("mousemove", this.mousemove);
|
13006
|
-
}
|
13007
|
-
}
|
13008
|
-
function isInTooltip(elt) {
|
13009
|
-
for (let cur = elt; cur; cur = cur.parentNode)
|
13010
|
-
if (cur.nodeType == 1 && cur.classList.contains("cm-tooltip"))
|
13011
|
-
return true;
|
13012
|
-
return false;
|
13013
|
-
}
|
13014
|
-
function isOverRange(view, from, to, x, y, margin) {
|
13015
|
-
let range = document.createRange();
|
13016
|
-
let fromDOM = view.domAtPos(from), toDOM = view.domAtPos(to);
|
13017
|
-
range.setEnd(toDOM.node, toDOM.offset);
|
13018
|
-
range.setStart(fromDOM.node, fromDOM.offset);
|
13019
|
-
let rects = range.getClientRects();
|
13020
|
-
range.detach();
|
13021
|
-
for (let i = 0; i < rects.length; i++) {
|
13022
|
-
let rect = rects[i];
|
13023
|
-
let dist = Math.max(rect.top - y, y - rect.bottom, rect.left - x, x - rect.right);
|
13024
|
-
if (dist <= margin)
|
13025
|
-
return true;
|
13026
|
-
}
|
13027
|
-
return false;
|
13028
|
-
}
|
13029
|
-
/**
|
13030
|
-
Set up a hover tooltip, which shows up when the pointer hovers
|
13031
|
-
over ranges of text. The callback is called when the mouse hovers
|
13032
|
-
over the document text. It should, if there is a tooltip
|
13033
|
-
associated with position `pos`, return the tooltip description
|
13034
|
-
(either directly or in a promise). The `side` argument indicates
|
13035
|
-
on which side of the position the pointer is—it will be -1 if the
|
13036
|
-
pointer is before the position, 1 if after the position.
|
13037
|
-
|
13038
|
-
Note that all hover tooltips are hosted within a single tooltip
|
13039
|
-
container element. This allows multiple tooltips over the same
|
13040
|
-
range to be "merged" together without overlapping.
|
13041
|
-
*/
|
13042
|
-
function hoverTooltip(source, options = {}) {
|
13043
|
-
let setHover = StateEffect.define();
|
13044
|
-
let hoverState = StateField.define({
|
13045
|
-
create() { return null; },
|
13046
|
-
update(value, tr) {
|
13047
|
-
if (value && (options.hideOnChange && (tr.docChanged || tr.selection) ||
|
13048
|
-
options.hideOn && options.hideOn(tr, value)))
|
13049
|
-
return null;
|
13050
|
-
if (value && tr.docChanged) {
|
13051
|
-
let newPos = tr.changes.mapPos(value.pos, -1, MapMode.TrackDel);
|
13052
|
-
if (newPos == null)
|
13053
|
-
return null;
|
13054
|
-
let copy = Object.assign(Object.create(null), value);
|
13055
|
-
copy.pos = newPos;
|
13056
|
-
if (value.end != null)
|
13057
|
-
copy.end = tr.changes.mapPos(value.end);
|
13058
|
-
value = copy;
|
13059
|
-
}
|
13060
|
-
for (let effect of tr.effects) {
|
13061
|
-
if (effect.is(setHover))
|
13062
|
-
value = effect.value;
|
13063
|
-
if (effect.is(closeHoverTooltipEffect))
|
13064
|
-
value = null;
|
13065
|
-
}
|
13066
|
-
return value;
|
13067
|
-
},
|
13068
|
-
provide: f => showHoverTooltip.from(f)
|
13069
|
-
});
|
13070
|
-
return [
|
13071
|
-
hoverState,
|
13072
|
-
ViewPlugin.define(view => new HoverPlugin(view, source, hoverState, setHover, options.hoverTime || 300 /* Hover.Time */)),
|
13073
|
-
showHoverTooltipHost
|
13074
|
-
];
|
13075
|
-
}
|
13076
12868
|
/**
|
13077
12869
|
Get the active tooltip view for a given tooltip, if available.
|
13078
12870
|
*/
|
@@ -13083,7 +12875,6 @@
|
|
13083
12875
|
let found = plugin.manager.tooltips.indexOf(tooltip);
|
13084
12876
|
return found < 0 ? null : plugin.manager.tooltipViews[found];
|
13085
12877
|
}
|
13086
|
-
const closeHoverTooltipEffect = /*@__PURE__*/StateEffect.define();
|
13087
12878
|
|
13088
12879
|
const panelConfig = /*@__PURE__*/Facet.define({
|
13089
12880
|
combine(configs) {
|
@@ -17145,7 +16936,7 @@
|
|
17145
16936
|
Create an extension that configures code folding.
|
17146
16937
|
*/
|
17147
16938
|
function codeFolding(config) {
|
17148
|
-
let result = [foldState, baseTheme$1$
|
16939
|
+
let result = [foldState, baseTheme$1$1];
|
17149
16940
|
if (config)
|
17150
16941
|
result.push(foldConfig.of(config));
|
17151
16942
|
return result;
|
@@ -17254,7 +17045,7 @@
|
|
17254
17045
|
codeFolding()
|
17255
17046
|
];
|
17256
17047
|
}
|
17257
|
-
const baseTheme$1$
|
17048
|
+
const baseTheme$1$1 = /*@__PURE__*/EditorView.baseTheme({
|
17258
17049
|
".cm-foldPlaceholder": {
|
17259
17050
|
backgroundColor: "#eee",
|
17260
17051
|
border: "1px solid #ddd",
|
@@ -19441,7 +19232,7 @@
|
|
19441
19232
|
if (!panel) {
|
19442
19233
|
let effects = [dialogEffect.of(true)];
|
19443
19234
|
if (view.state.field(dialogField, false) == null)
|
19444
|
-
effects.push(StateEffect.appendConfig.of([dialogField, baseTheme$1
|
19235
|
+
effects.push(StateEffect.appendConfig.of([dialogField, baseTheme$1]));
|
19445
19236
|
view.dispatch({ effects });
|
19446
19237
|
panel = getPanel(view, createLineDialog);
|
19447
19238
|
}
|
@@ -19449,7 +19240,7 @@
|
|
19449
19240
|
panel.dom.querySelector("input").focus();
|
19450
19241
|
return true;
|
19451
19242
|
};
|
19452
|
-
const baseTheme$1
|
19243
|
+
const baseTheme$1 = /*@__PURE__*/EditorView.baseTheme({
|
19453
19244
|
".cm-panel.cm-gotoLine": {
|
19454
19245
|
padding: "2px 6px 4px",
|
19455
19246
|
"& label": { fontSize: "80%" }
|
@@ -19811,7 +19602,7 @@
|
|
19811
19602
|
once).
|
19812
19603
|
*/
|
19813
19604
|
const setSearchQuery = /*@__PURE__*/StateEffect.define();
|
19814
|
-
const togglePanel
|
19605
|
+
const togglePanel = /*@__PURE__*/StateEffect.define();
|
19815
19606
|
const searchState = /*@__PURE__*/StateField.define({
|
19816
19607
|
create(state) {
|
19817
19608
|
return new SearchState(defaultQuery(state).create(), null);
|
@@ -19820,7 +19611,7 @@
|
|
19820
19611
|
for (let effect of tr.effects) {
|
19821
19612
|
if (effect.is(setSearchQuery))
|
19822
19613
|
value = new SearchState(effect.value.create(), value.panel);
|
19823
|
-
else if (effect.is(togglePanel
|
19614
|
+
else if (effect.is(togglePanel))
|
19824
19615
|
value = new SearchState(value.query, effect.value ? createSearchPanel : null);
|
19825
19616
|
}
|
19826
19617
|
return value;
|
@@ -20031,7 +19822,7 @@
|
|
20031
19822
|
}
|
20032
19823
|
else {
|
20033
19824
|
view.dispatch({ effects: [
|
20034
|
-
togglePanel
|
19825
|
+
togglePanel.of(true),
|
20035
19826
|
state ? setSearchQuery.of(defaultQuery(view.state, state.query.spec)) : StateEffect.appendConfig.of(searchExtensions)
|
20036
19827
|
] });
|
20037
19828
|
}
|
@@ -20047,7 +19838,7 @@
|
|
20047
19838
|
let panel = getPanel(view, createSearchPanel);
|
20048
19839
|
if (panel && panel.dom.contains(view.root.activeElement))
|
20049
19840
|
view.focus();
|
20050
|
-
view.dispatch({ effects: togglePanel
|
19841
|
+
view.dispatch({ effects: togglePanel.of(false) });
|
20051
19842
|
return true;
|
20052
19843
|
};
|
20053
19844
|
/**
|
@@ -21314,7 +21105,7 @@
|
|
21314
21105
|
}
|
21315
21106
|
});
|
21316
21107
|
|
21317
|
-
const baseTheme
|
21108
|
+
const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
21318
21109
|
".cm-tooltip.cm-tooltip-autocomplete": {
|
21319
21110
|
"& > ul": {
|
21320
21111
|
fontFamily: "monospace",
|
@@ -21690,7 +21481,7 @@
|
|
21690
21481
|
completionConfig.of(config),
|
21691
21482
|
completionPlugin,
|
21692
21483
|
completionKeymapExt,
|
21693
|
-
baseTheme
|
21484
|
+
baseTheme
|
21694
21485
|
];
|
21695
21486
|
}
|
21696
21487
|
/**
|
@@ -21715,568 +21506,6 @@
|
|
21715
21506
|
];
|
21716
21507
|
const completionKeymapExt = /*@__PURE__*/Prec.highest(/*@__PURE__*/keymap.computeN([completionConfig], state => state.facet(completionConfig).defaultKeymap ? [completionKeymap] : []));
|
21717
21508
|
|
21718
|
-
class SelectedDiagnostic {
|
21719
|
-
constructor(from, to, diagnostic) {
|
21720
|
-
this.from = from;
|
21721
|
-
this.to = to;
|
21722
|
-
this.diagnostic = diagnostic;
|
21723
|
-
}
|
21724
|
-
}
|
21725
|
-
class LintState {
|
21726
|
-
constructor(diagnostics, panel, selected) {
|
21727
|
-
this.diagnostics = diagnostics;
|
21728
|
-
this.panel = panel;
|
21729
|
-
this.selected = selected;
|
21730
|
-
}
|
21731
|
-
static init(diagnostics, panel, state) {
|
21732
|
-
// Filter the list of diagnostics for which to create markers
|
21733
|
-
let markedDiagnostics = diagnostics;
|
21734
|
-
let diagnosticFilter = state.facet(lintConfig).markerFilter;
|
21735
|
-
if (diagnosticFilter)
|
21736
|
-
markedDiagnostics = diagnosticFilter(markedDiagnostics);
|
21737
|
-
let ranges = Decoration.set(markedDiagnostics.map((d) => {
|
21738
|
-
// For zero-length ranges or ranges covering only a line break, create a widget
|
21739
|
-
return d.from == d.to || (d.from == d.to - 1 && state.doc.lineAt(d.from).to == d.from)
|
21740
|
-
? Decoration.widget({
|
21741
|
-
widget: new DiagnosticWidget(d),
|
21742
|
-
diagnostic: d
|
21743
|
-
}).range(d.from)
|
21744
|
-
: Decoration.mark({
|
21745
|
-
attributes: { class: "cm-lintRange cm-lintRange-" + d.severity },
|
21746
|
-
diagnostic: d
|
21747
|
-
}).range(d.from, d.to);
|
21748
|
-
}), true);
|
21749
|
-
return new LintState(ranges, panel, findDiagnostic(ranges));
|
21750
|
-
}
|
21751
|
-
}
|
21752
|
-
function findDiagnostic(diagnostics, diagnostic = null, after = 0) {
|
21753
|
-
let found = null;
|
21754
|
-
diagnostics.between(after, 1e9, (from, to, { spec }) => {
|
21755
|
-
if (diagnostic && spec.diagnostic != diagnostic)
|
21756
|
-
return;
|
21757
|
-
found = new SelectedDiagnostic(from, to, spec.diagnostic);
|
21758
|
-
return false;
|
21759
|
-
});
|
21760
|
-
return found;
|
21761
|
-
}
|
21762
|
-
function hideTooltip(tr, tooltip) {
|
21763
|
-
return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(tooltip.pos));
|
21764
|
-
}
|
21765
|
-
function maybeEnableLint(state, effects) {
|
21766
|
-
return state.field(lintState, false) ? effects : effects.concat(StateEffect.appendConfig.of([
|
21767
|
-
lintState,
|
21768
|
-
EditorView.decorations.compute([lintState], state => {
|
21769
|
-
let { selected, panel } = state.field(lintState);
|
21770
|
-
return !selected || !panel || selected.from == selected.to ? Decoration.none : Decoration.set([
|
21771
|
-
activeMark.range(selected.from, selected.to)
|
21772
|
-
]);
|
21773
|
-
}),
|
21774
|
-
hoverTooltip(lintTooltip, { hideOn: hideTooltip }),
|
21775
|
-
baseTheme
|
21776
|
-
]));
|
21777
|
-
}
|
21778
|
-
/**
|
21779
|
-
Returns a transaction spec which updates the current set of
|
21780
|
-
diagnostics, and enables the lint extension if if wasn't already
|
21781
|
-
active.
|
21782
|
-
*/
|
21783
|
-
function setDiagnostics(state, diagnostics) {
|
21784
|
-
return {
|
21785
|
-
effects: maybeEnableLint(state, [setDiagnosticsEffect.of(diagnostics)])
|
21786
|
-
};
|
21787
|
-
}
|
21788
|
-
/**
|
21789
|
-
The state effect that updates the set of active diagnostics. Can
|
21790
|
-
be useful when writing an extension that needs to track these.
|
21791
|
-
*/
|
21792
|
-
const setDiagnosticsEffect = /*@__PURE__*/StateEffect.define();
|
21793
|
-
const togglePanel = /*@__PURE__*/StateEffect.define();
|
21794
|
-
const movePanelSelection = /*@__PURE__*/StateEffect.define();
|
21795
|
-
const lintState = /*@__PURE__*/StateField.define({
|
21796
|
-
create() {
|
21797
|
-
return new LintState(Decoration.none, null, null);
|
21798
|
-
},
|
21799
|
-
update(value, tr) {
|
21800
|
-
if (tr.docChanged) {
|
21801
|
-
let mapped = value.diagnostics.map(tr.changes), selected = null;
|
21802
|
-
if (value.selected) {
|
21803
|
-
let selPos = tr.changes.mapPos(value.selected.from, 1);
|
21804
|
-
selected = findDiagnostic(mapped, value.selected.diagnostic, selPos) || findDiagnostic(mapped, null, selPos);
|
21805
|
-
}
|
21806
|
-
value = new LintState(mapped, value.panel, selected);
|
21807
|
-
}
|
21808
|
-
for (let effect of tr.effects) {
|
21809
|
-
if (effect.is(setDiagnosticsEffect)) {
|
21810
|
-
value = LintState.init(effect.value, value.panel, tr.state);
|
21811
|
-
}
|
21812
|
-
else if (effect.is(togglePanel)) {
|
21813
|
-
value = new LintState(value.diagnostics, effect.value ? LintPanel.open : null, value.selected);
|
21814
|
-
}
|
21815
|
-
else if (effect.is(movePanelSelection)) {
|
21816
|
-
value = new LintState(value.diagnostics, value.panel, effect.value);
|
21817
|
-
}
|
21818
|
-
}
|
21819
|
-
return value;
|
21820
|
-
},
|
21821
|
-
provide: f => [showPanel.from(f, val => val.panel),
|
21822
|
-
EditorView.decorations.from(f, s => s.diagnostics)]
|
21823
|
-
});
|
21824
|
-
const activeMark = /*@__PURE__*/Decoration.mark({ class: "cm-lintRange cm-lintRange-active" });
|
21825
|
-
function lintTooltip(view, pos, side) {
|
21826
|
-
let { diagnostics } = view.state.field(lintState);
|
21827
|
-
let found = [], stackStart = 2e8, stackEnd = 0;
|
21828
|
-
diagnostics.between(pos - (side < 0 ? 1 : 0), pos + (side > 0 ? 1 : 0), (from, to, { spec }) => {
|
21829
|
-
if (pos >= from && pos <= to &&
|
21830
|
-
(from == to || ((pos > from || side > 0) && (pos < to || side < 0)))) {
|
21831
|
-
found.push(spec.diagnostic);
|
21832
|
-
stackStart = Math.min(from, stackStart);
|
21833
|
-
stackEnd = Math.max(to, stackEnd);
|
21834
|
-
}
|
21835
|
-
});
|
21836
|
-
let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;
|
21837
|
-
if (diagnosticFilter)
|
21838
|
-
found = diagnosticFilter(found);
|
21839
|
-
if (!found.length)
|
21840
|
-
return null;
|
21841
|
-
return {
|
21842
|
-
pos: stackStart,
|
21843
|
-
end: stackEnd,
|
21844
|
-
above: view.state.doc.lineAt(stackStart).to < stackEnd,
|
21845
|
-
create() {
|
21846
|
-
return { dom: diagnosticsTooltip(view, found) };
|
21847
|
-
}
|
21848
|
-
};
|
21849
|
-
}
|
21850
|
-
function diagnosticsTooltip(view, diagnostics) {
|
21851
|
-
return crelt("ul", { class: "cm-tooltip-lint" }, diagnostics.map(d => renderDiagnostic(view, d, false)));
|
21852
|
-
}
|
21853
|
-
/**
|
21854
|
-
Command to open and focus the lint panel.
|
21855
|
-
*/
|
21856
|
-
const openLintPanel = (view) => {
|
21857
|
-
let field = view.state.field(lintState, false);
|
21858
|
-
if (!field || !field.panel)
|
21859
|
-
view.dispatch({ effects: maybeEnableLint(view.state, [togglePanel.of(true)]) });
|
21860
|
-
let panel = getPanel(view, LintPanel.open);
|
21861
|
-
if (panel)
|
21862
|
-
panel.dom.querySelector(".cm-panel-lint ul").focus();
|
21863
|
-
return true;
|
21864
|
-
};
|
21865
|
-
/**
|
21866
|
-
Command to close the lint panel, when open.
|
21867
|
-
*/
|
21868
|
-
const closeLintPanel = (view) => {
|
21869
|
-
let field = view.state.field(lintState, false);
|
21870
|
-
if (!field || !field.panel)
|
21871
|
-
return false;
|
21872
|
-
view.dispatch({ effects: togglePanel.of(false) });
|
21873
|
-
return true;
|
21874
|
-
};
|
21875
|
-
/**
|
21876
|
-
Move the selection to the next diagnostic.
|
21877
|
-
*/
|
21878
|
-
const nextDiagnostic = (view) => {
|
21879
|
-
let field = view.state.field(lintState, false);
|
21880
|
-
if (!field)
|
21881
|
-
return false;
|
21882
|
-
let sel = view.state.selection.main, next = field.diagnostics.iter(sel.to + 1);
|
21883
|
-
if (!next.value) {
|
21884
|
-
next = field.diagnostics.iter(0);
|
21885
|
-
if (!next.value || next.from == sel.from && next.to == sel.to)
|
21886
|
-
return false;
|
21887
|
-
}
|
21888
|
-
view.dispatch({ selection: { anchor: next.from, head: next.to }, scrollIntoView: true });
|
21889
|
-
return true;
|
21890
|
-
};
|
21891
|
-
/**
|
21892
|
-
A set of default key bindings for the lint functionality.
|
21893
|
-
|
21894
|
-
- Ctrl-Shift-m (Cmd-Shift-m on macOS): [`openLintPanel`](https://codemirror.net/6/docs/ref/#lint.openLintPanel)
|
21895
|
-
- F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic)
|
21896
|
-
*/
|
21897
|
-
const lintKeymap = [
|
21898
|
-
{ key: "Mod-Shift-m", run: openLintPanel, preventDefault: true },
|
21899
|
-
{ key: "F8", run: nextDiagnostic }
|
21900
|
-
];
|
21901
|
-
const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
21902
|
-
constructor(view) {
|
21903
|
-
this.view = view;
|
21904
|
-
this.timeout = -1;
|
21905
|
-
this.set = true;
|
21906
|
-
let { delay } = view.state.facet(lintConfig);
|
21907
|
-
this.lintTime = Date.now() + delay;
|
21908
|
-
this.run = this.run.bind(this);
|
21909
|
-
this.timeout = setTimeout(this.run, delay);
|
21910
|
-
}
|
21911
|
-
run() {
|
21912
|
-
let now = Date.now();
|
21913
|
-
if (now < this.lintTime - 10) {
|
21914
|
-
setTimeout(this.run, this.lintTime - now);
|
21915
|
-
}
|
21916
|
-
else {
|
21917
|
-
this.set = false;
|
21918
|
-
let { state } = this.view, { sources } = state.facet(lintConfig);
|
21919
|
-
Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => {
|
21920
|
-
let all = annotations.reduce((a, b) => a.concat(b));
|
21921
|
-
if (this.view.state.doc == state.doc)
|
21922
|
-
this.view.dispatch(setDiagnostics(this.view.state, all));
|
21923
|
-
}, error => { logException(this.view.state, error); });
|
21924
|
-
}
|
21925
|
-
}
|
21926
|
-
update(update) {
|
21927
|
-
let config = update.state.facet(lintConfig);
|
21928
|
-
if (update.docChanged || config != update.startState.facet(lintConfig) ||
|
21929
|
-
config.needsRefresh && config.needsRefresh(update)) {
|
21930
|
-
this.lintTime = Date.now() + config.delay;
|
21931
|
-
if (!this.set) {
|
21932
|
-
this.set = true;
|
21933
|
-
this.timeout = setTimeout(this.run, config.delay);
|
21934
|
-
}
|
21935
|
-
}
|
21936
|
-
}
|
21937
|
-
force() {
|
21938
|
-
if (this.set) {
|
21939
|
-
this.lintTime = Date.now();
|
21940
|
-
this.run();
|
21941
|
-
}
|
21942
|
-
}
|
21943
|
-
destroy() {
|
21944
|
-
clearTimeout(this.timeout);
|
21945
|
-
}
|
21946
|
-
});
|
21947
|
-
const lintConfig = /*@__PURE__*/Facet.define({
|
21948
|
-
combine(input) {
|
21949
|
-
return Object.assign({ sources: input.map(i => i.source) }, combineConfig(input.map(i => i.config), {
|
21950
|
-
delay: 750,
|
21951
|
-
markerFilter: null,
|
21952
|
-
tooltipFilter: null,
|
21953
|
-
needsRefresh: null
|
21954
|
-
}, {
|
21955
|
-
needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u)
|
21956
|
-
}));
|
21957
|
-
},
|
21958
|
-
enables: lintPlugin
|
21959
|
-
});
|
21960
|
-
function assignKeys(actions) {
|
21961
|
-
let assigned = [];
|
21962
|
-
if (actions)
|
21963
|
-
actions: for (let { name } of actions) {
|
21964
|
-
for (let i = 0; i < name.length; i++) {
|
21965
|
-
let ch = name[i];
|
21966
|
-
if (/[a-zA-Z]/.test(ch) && !assigned.some(c => c.toLowerCase() == ch.toLowerCase())) {
|
21967
|
-
assigned.push(ch);
|
21968
|
-
continue actions;
|
21969
|
-
}
|
21970
|
-
}
|
21971
|
-
assigned.push("");
|
21972
|
-
}
|
21973
|
-
return assigned;
|
21974
|
-
}
|
21975
|
-
function renderDiagnostic(view, diagnostic, inPanel) {
|
21976
|
-
var _a;
|
21977
|
-
let keys = inPanel ? assignKeys(diagnostic.actions) : [];
|
21978
|
-
return crelt("li", { class: "cm-diagnostic cm-diagnostic-" + diagnostic.severity }, crelt("span", { class: "cm-diagnosticText" }, diagnostic.renderMessage ? diagnostic.renderMessage() : diagnostic.message), (_a = diagnostic.actions) === null || _a === void 0 ? void 0 : _a.map((action, i) => {
|
21979
|
-
let fired = false, click = (e) => {
|
21980
|
-
e.preventDefault();
|
21981
|
-
if (fired)
|
21982
|
-
return;
|
21983
|
-
fired = true;
|
21984
|
-
let found = findDiagnostic(view.state.field(lintState).diagnostics, diagnostic);
|
21985
|
-
if (found)
|
21986
|
-
action.apply(view, found.from, found.to);
|
21987
|
-
};
|
21988
|
-
let { name } = action, keyIndex = keys[i] ? name.indexOf(keys[i]) : -1;
|
21989
|
-
let nameElt = keyIndex < 0 ? name : [name.slice(0, keyIndex),
|
21990
|
-
crelt("u", name.slice(keyIndex, keyIndex + 1)),
|
21991
|
-
name.slice(keyIndex + 1)];
|
21992
|
-
return crelt("button", {
|
21993
|
-
type: "button",
|
21994
|
-
class: "cm-diagnosticAction",
|
21995
|
-
onclick: click,
|
21996
|
-
onmousedown: click,
|
21997
|
-
"aria-label": ` Action: ${name}${keyIndex < 0 ? "" : ` (access key "${keys[i]})"`}.`
|
21998
|
-
}, nameElt);
|
21999
|
-
}), diagnostic.source && crelt("div", { class: "cm-diagnosticSource" }, diagnostic.source));
|
22000
|
-
}
|
22001
|
-
class DiagnosticWidget extends WidgetType {
|
22002
|
-
constructor(diagnostic) {
|
22003
|
-
super();
|
22004
|
-
this.diagnostic = diagnostic;
|
22005
|
-
}
|
22006
|
-
eq(other) { return other.diagnostic == this.diagnostic; }
|
22007
|
-
toDOM() {
|
22008
|
-
return crelt("span", { class: "cm-lintPoint cm-lintPoint-" + this.diagnostic.severity });
|
22009
|
-
}
|
22010
|
-
}
|
22011
|
-
class PanelItem {
|
22012
|
-
constructor(view, diagnostic) {
|
22013
|
-
this.diagnostic = diagnostic;
|
22014
|
-
this.id = "item_" + Math.floor(Math.random() * 0xffffffff).toString(16);
|
22015
|
-
this.dom = renderDiagnostic(view, diagnostic, true);
|
22016
|
-
this.dom.id = this.id;
|
22017
|
-
this.dom.setAttribute("role", "option");
|
22018
|
-
}
|
22019
|
-
}
|
22020
|
-
class LintPanel {
|
22021
|
-
constructor(view) {
|
22022
|
-
this.view = view;
|
22023
|
-
this.items = [];
|
22024
|
-
let onkeydown = (event) => {
|
22025
|
-
if (event.keyCode == 27) { // Escape
|
22026
|
-
closeLintPanel(this.view);
|
22027
|
-
this.view.focus();
|
22028
|
-
}
|
22029
|
-
else if (event.keyCode == 38 || event.keyCode == 33) { // ArrowUp, PageUp
|
22030
|
-
this.moveSelection((this.selectedIndex - 1 + this.items.length) % this.items.length);
|
22031
|
-
}
|
22032
|
-
else if (event.keyCode == 40 || event.keyCode == 34) { // ArrowDown, PageDown
|
22033
|
-
this.moveSelection((this.selectedIndex + 1) % this.items.length);
|
22034
|
-
}
|
22035
|
-
else if (event.keyCode == 36) { // Home
|
22036
|
-
this.moveSelection(0);
|
22037
|
-
}
|
22038
|
-
else if (event.keyCode == 35) { // End
|
22039
|
-
this.moveSelection(this.items.length - 1);
|
22040
|
-
}
|
22041
|
-
else if (event.keyCode == 13) { // Enter
|
22042
|
-
this.view.focus();
|
22043
|
-
}
|
22044
|
-
else if (event.keyCode >= 65 && event.keyCode <= 90 && this.selectedIndex >= 0) { // A-Z
|
22045
|
-
let { diagnostic } = this.items[this.selectedIndex], keys = assignKeys(diagnostic.actions);
|
22046
|
-
for (let i = 0; i < keys.length; i++)
|
22047
|
-
if (keys[i].toUpperCase().charCodeAt(0) == event.keyCode) {
|
22048
|
-
let found = findDiagnostic(this.view.state.field(lintState).diagnostics, diagnostic);
|
22049
|
-
if (found)
|
22050
|
-
diagnostic.actions[i].apply(view, found.from, found.to);
|
22051
|
-
}
|
22052
|
-
}
|
22053
|
-
else {
|
22054
|
-
return;
|
22055
|
-
}
|
22056
|
-
event.preventDefault();
|
22057
|
-
};
|
22058
|
-
let onclick = (event) => {
|
22059
|
-
for (let i = 0; i < this.items.length; i++) {
|
22060
|
-
if (this.items[i].dom.contains(event.target))
|
22061
|
-
this.moveSelection(i);
|
22062
|
-
}
|
22063
|
-
};
|
22064
|
-
this.list = crelt("ul", {
|
22065
|
-
tabIndex: 0,
|
22066
|
-
role: "listbox",
|
22067
|
-
"aria-label": this.view.state.phrase("Diagnostics"),
|
22068
|
-
onkeydown,
|
22069
|
-
onclick
|
22070
|
-
});
|
22071
|
-
this.dom = crelt("div", { class: "cm-panel-lint" }, this.list, crelt("button", {
|
22072
|
-
type: "button",
|
22073
|
-
name: "close",
|
22074
|
-
"aria-label": this.view.state.phrase("close"),
|
22075
|
-
onclick: () => closeLintPanel(this.view)
|
22076
|
-
}, "×"));
|
22077
|
-
this.update();
|
22078
|
-
}
|
22079
|
-
get selectedIndex() {
|
22080
|
-
let selected = this.view.state.field(lintState).selected;
|
22081
|
-
if (!selected)
|
22082
|
-
return -1;
|
22083
|
-
for (let i = 0; i < this.items.length; i++)
|
22084
|
-
if (this.items[i].diagnostic == selected.diagnostic)
|
22085
|
-
return i;
|
22086
|
-
return -1;
|
22087
|
-
}
|
22088
|
-
update() {
|
22089
|
-
let { diagnostics, selected } = this.view.state.field(lintState);
|
22090
|
-
let i = 0, needsSync = false, newSelectedItem = null;
|
22091
|
-
diagnostics.between(0, this.view.state.doc.length, (_start, _end, { spec }) => {
|
22092
|
-
let found = -1, item;
|
22093
|
-
for (let j = i; j < this.items.length; j++)
|
22094
|
-
if (this.items[j].diagnostic == spec.diagnostic) {
|
22095
|
-
found = j;
|
22096
|
-
break;
|
22097
|
-
}
|
22098
|
-
if (found < 0) {
|
22099
|
-
item = new PanelItem(this.view, spec.diagnostic);
|
22100
|
-
this.items.splice(i, 0, item);
|
22101
|
-
needsSync = true;
|
22102
|
-
}
|
22103
|
-
else {
|
22104
|
-
item = this.items[found];
|
22105
|
-
if (found > i) {
|
22106
|
-
this.items.splice(i, found - i);
|
22107
|
-
needsSync = true;
|
22108
|
-
}
|
22109
|
-
}
|
22110
|
-
if (selected && item.diagnostic == selected.diagnostic) {
|
22111
|
-
if (!item.dom.hasAttribute("aria-selected")) {
|
22112
|
-
item.dom.setAttribute("aria-selected", "true");
|
22113
|
-
newSelectedItem = item;
|
22114
|
-
}
|
22115
|
-
}
|
22116
|
-
else if (item.dom.hasAttribute("aria-selected")) {
|
22117
|
-
item.dom.removeAttribute("aria-selected");
|
22118
|
-
}
|
22119
|
-
i++;
|
22120
|
-
});
|
22121
|
-
while (i < this.items.length && !(this.items.length == 1 && this.items[0].diagnostic.from < 0)) {
|
22122
|
-
needsSync = true;
|
22123
|
-
this.items.pop();
|
22124
|
-
}
|
22125
|
-
if (this.items.length == 0) {
|
22126
|
-
this.items.push(new PanelItem(this.view, {
|
22127
|
-
from: -1, to: -1,
|
22128
|
-
severity: "info",
|
22129
|
-
message: this.view.state.phrase("No diagnostics")
|
22130
|
-
}));
|
22131
|
-
needsSync = true;
|
22132
|
-
}
|
22133
|
-
if (newSelectedItem) {
|
22134
|
-
this.list.setAttribute("aria-activedescendant", newSelectedItem.id);
|
22135
|
-
this.view.requestMeasure({
|
22136
|
-
key: this,
|
22137
|
-
read: () => ({ sel: newSelectedItem.dom.getBoundingClientRect(), panel: this.list.getBoundingClientRect() }),
|
22138
|
-
write: ({ sel, panel }) => {
|
22139
|
-
if (sel.top < panel.top)
|
22140
|
-
this.list.scrollTop -= panel.top - sel.top;
|
22141
|
-
else if (sel.bottom > panel.bottom)
|
22142
|
-
this.list.scrollTop += sel.bottom - panel.bottom;
|
22143
|
-
}
|
22144
|
-
});
|
22145
|
-
}
|
22146
|
-
else if (this.selectedIndex < 0) {
|
22147
|
-
this.list.removeAttribute("aria-activedescendant");
|
22148
|
-
}
|
22149
|
-
if (needsSync)
|
22150
|
-
this.sync();
|
22151
|
-
}
|
22152
|
-
sync() {
|
22153
|
-
let domPos = this.list.firstChild;
|
22154
|
-
function rm() {
|
22155
|
-
let prev = domPos;
|
22156
|
-
domPos = prev.nextSibling;
|
22157
|
-
prev.remove();
|
22158
|
-
}
|
22159
|
-
for (let item of this.items) {
|
22160
|
-
if (item.dom.parentNode == this.list) {
|
22161
|
-
while (domPos != item.dom)
|
22162
|
-
rm();
|
22163
|
-
domPos = item.dom.nextSibling;
|
22164
|
-
}
|
22165
|
-
else {
|
22166
|
-
this.list.insertBefore(item.dom, domPos);
|
22167
|
-
}
|
22168
|
-
}
|
22169
|
-
while (domPos)
|
22170
|
-
rm();
|
22171
|
-
}
|
22172
|
-
moveSelection(selectedIndex) {
|
22173
|
-
if (this.selectedIndex < 0)
|
22174
|
-
return;
|
22175
|
-
let field = this.view.state.field(lintState);
|
22176
|
-
let selection = findDiagnostic(field.diagnostics, this.items[selectedIndex].diagnostic);
|
22177
|
-
if (!selection)
|
22178
|
-
return;
|
22179
|
-
this.view.dispatch({
|
22180
|
-
selection: { anchor: selection.from, head: selection.to },
|
22181
|
-
scrollIntoView: true,
|
22182
|
-
effects: movePanelSelection.of(selection)
|
22183
|
-
});
|
22184
|
-
}
|
22185
|
-
static open(view) { return new LintPanel(view); }
|
22186
|
-
}
|
22187
|
-
function svg(content, attrs = `viewBox="0 0 40 40"`) {
|
22188
|
-
return `url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" ${attrs}>${encodeURIComponent(content)}</svg>')`;
|
22189
|
-
}
|
22190
|
-
function underline(color) {
|
22191
|
-
return svg(`<path d="m0 2.5 l2 -1.5 l1 0 l2 1.5 l1 0" stroke="${color}" fill="none" stroke-width=".7"/>`, `width="6" height="3"`);
|
22192
|
-
}
|
22193
|
-
const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
22194
|
-
".cm-diagnostic": {
|
22195
|
-
padding: "3px 6px 3px 8px",
|
22196
|
-
marginLeft: "-1px",
|
22197
|
-
display: "block",
|
22198
|
-
whiteSpace: "pre-wrap"
|
22199
|
-
},
|
22200
|
-
".cm-diagnostic-error": { borderLeft: "5px solid #d11" },
|
22201
|
-
".cm-diagnostic-warning": { borderLeft: "5px solid orange" },
|
22202
|
-
".cm-diagnostic-info": { borderLeft: "5px solid #999" },
|
22203
|
-
".cm-diagnosticAction": {
|
22204
|
-
font: "inherit",
|
22205
|
-
border: "none",
|
22206
|
-
padding: "2px 4px",
|
22207
|
-
backgroundColor: "#444",
|
22208
|
-
color: "white",
|
22209
|
-
borderRadius: "3px",
|
22210
|
-
marginLeft: "8px",
|
22211
|
-
cursor: "pointer"
|
22212
|
-
},
|
22213
|
-
".cm-diagnosticSource": {
|
22214
|
-
fontSize: "70%",
|
22215
|
-
opacity: .7
|
22216
|
-
},
|
22217
|
-
".cm-lintRange": {
|
22218
|
-
backgroundPosition: "left bottom",
|
22219
|
-
backgroundRepeat: "repeat-x",
|
22220
|
-
paddingBottom: "0.7px",
|
22221
|
-
},
|
22222
|
-
".cm-lintRange-error": { backgroundImage: /*@__PURE__*/underline("#d11") },
|
22223
|
-
".cm-lintRange-warning": { backgroundImage: /*@__PURE__*/underline("orange") },
|
22224
|
-
".cm-lintRange-info": { backgroundImage: /*@__PURE__*/underline("#999") },
|
22225
|
-
".cm-lintRange-active": { backgroundColor: "#ffdd9980" },
|
22226
|
-
".cm-tooltip-lint": {
|
22227
|
-
padding: 0,
|
22228
|
-
margin: 0
|
22229
|
-
},
|
22230
|
-
".cm-lintPoint": {
|
22231
|
-
position: "relative",
|
22232
|
-
"&:after": {
|
22233
|
-
content: '""',
|
22234
|
-
position: "absolute",
|
22235
|
-
bottom: 0,
|
22236
|
-
left: "-2px",
|
22237
|
-
borderLeft: "3px solid transparent",
|
22238
|
-
borderRight: "3px solid transparent",
|
22239
|
-
borderBottom: "4px solid #d11"
|
22240
|
-
}
|
22241
|
-
},
|
22242
|
-
".cm-lintPoint-warning": {
|
22243
|
-
"&:after": { borderBottomColor: "orange" }
|
22244
|
-
},
|
22245
|
-
".cm-lintPoint-info": {
|
22246
|
-
"&:after": { borderBottomColor: "#999" }
|
22247
|
-
},
|
22248
|
-
".cm-panel.cm-panel-lint": {
|
22249
|
-
position: "relative",
|
22250
|
-
"& ul": {
|
22251
|
-
maxHeight: "100px",
|
22252
|
-
overflowY: "auto",
|
22253
|
-
"& [aria-selected]": {
|
22254
|
-
backgroundColor: "#ddd",
|
22255
|
-
"& u": { textDecoration: "underline" }
|
22256
|
-
},
|
22257
|
-
"&:focus [aria-selected]": {
|
22258
|
-
background_fallback: "#bdf",
|
22259
|
-
backgroundColor: "Highlight",
|
22260
|
-
color_fallback: "white",
|
22261
|
-
color: "HighlightText"
|
22262
|
-
},
|
22263
|
-
"& u": { textDecoration: "none" },
|
22264
|
-
padding: 0,
|
22265
|
-
margin: 0
|
22266
|
-
},
|
22267
|
-
"& [name=close]": {
|
22268
|
-
position: "absolute",
|
22269
|
-
top: "0",
|
22270
|
-
right: "2px",
|
22271
|
-
background: "inherit",
|
22272
|
-
border: "none",
|
22273
|
-
font: "inherit",
|
22274
|
-
padding: 0,
|
22275
|
-
margin: 0
|
22276
|
-
}
|
22277
|
-
}
|
22278
|
-
});
|
22279
|
-
|
22280
21509
|
function base64Encode (str) {
|
22281
21510
|
// https://stackoverflow.com/questions/30106476/using-javascripts-atob-to-decode-base64-doesnt-properly-decode-utf-8-strings
|
22282
21511
|
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
|
@@ -24653,8 +23882,7 @@
|
|
24653
23882
|
...searchKeymap,
|
24654
23883
|
...historyKeymap,
|
24655
23884
|
...foldKeymap,
|
24656
|
-
...completionKeymap
|
24657
|
-
...lintKeymap
|
23885
|
+
...completionKeymap
|
24658
23886
|
]);
|
24659
23887
|
const sqlConfig = {
|
24660
23888
|
dialect: MySQL,
|
@@ -25185,12 +24413,19 @@
|
|
25185
24413
|
closeElement.focus();
|
25186
24414
|
}
|
25187
24415
|
|
24416
|
+
function closePopup () {
|
24417
|
+
const wrapperElement = document.getElementById('popup-wrapper');
|
24418
|
+
if (wrapperElement) {
|
24419
|
+
document.body.removeChild(wrapperElement);
|
24420
|
+
return true
|
24421
|
+
}
|
24422
|
+
return false
|
24423
|
+
}
|
24424
|
+
|
25188
24425
|
document.addEventListener('keydown', (event) => {
|
25189
24426
|
if (event.code === 'Escape') {
|
25190
|
-
|
25191
|
-
if (wrapperElement) {
|
24427
|
+
if (closePopup()) {
|
25192
24428
|
event.preventDefault();
|
25193
|
-
document.body.removeChild(wrapperElement);
|
25194
24429
|
}
|
25195
24430
|
} else if (event.code === 'Tab') {
|
25196
24431
|
const wrapperElement = document.getElementById('popup-wrapper');
|
@@ -25403,14 +24638,24 @@
|
|
25403
24638
|
|
25404
24639
|
function focus (selection = null) {
|
25405
24640
|
window.editorView.focus();
|
25406
|
-
if (selection)
|
24641
|
+
if (selection) {
|
24642
|
+
setSelection(selection);
|
24643
|
+
}
|
25407
24644
|
}
|
25408
24645
|
|
25409
|
-
function
|
24646
|
+
function getEditorValue () {
|
25410
24647
|
return window.editorView.state.doc.toString()
|
25411
24648
|
}
|
25412
24649
|
|
25413
|
-
function
|
24650
|
+
function isLastEditorValueSet (value) {
|
24651
|
+
return window.lastEditorValueSet === value
|
24652
|
+
}
|
24653
|
+
|
24654
|
+
function setEditorValue (value) {
|
24655
|
+
window.lastEditorValueSet = value;
|
24656
|
+
if (getEditorValue() === value) {
|
24657
|
+
return
|
24658
|
+
}
|
25414
24659
|
window.editorView.dispatch({
|
25415
24660
|
changes: {
|
25416
24661
|
from: 0,
|
@@ -25454,6 +24699,8 @@
|
|
25454
24699
|
}
|
25455
24700
|
|
25456
24701
|
function route (target = null, event = null, url = null, internal = false) {
|
24702
|
+
closePopup();
|
24703
|
+
|
25457
24704
|
if (url) {
|
25458
24705
|
if (event) {
|
25459
24706
|
event.preventDefault();
|
@@ -25493,7 +24740,7 @@
|
|
25493
24740
|
|
25494
24741
|
switch (window.tab) {
|
25495
24742
|
case 'query':
|
25496
|
-
|
24743
|
+
selectQueryTab(internal);
|
25497
24744
|
break
|
25498
24745
|
case 'graph':
|
25499
24746
|
selectGraphTab(internal);
|
@@ -25534,42 +24781,53 @@
|
|
25534
24781
|
selected.style.display = 'flex';
|
25535
24782
|
});
|
25536
24783
|
|
24784
|
+
const schemaNames = Object.keys(window.metadata.schemas);
|
24785
|
+
const schemasElement = document.getElementById('schemas');
|
24786
|
+
const tablesElement = document.getElementById('tables');
|
24787
|
+
if (schemaNames.length === 1) {
|
24788
|
+
setTimeout(() => { tablesElement.focus(); }, 0);
|
24789
|
+
} else {
|
24790
|
+
setTimeout(() => { schemasElement.focus(); }, 0);
|
24791
|
+
}
|
24792
|
+
|
25537
24793
|
if (window.structureLoaded) {
|
25538
24794
|
return
|
25539
24795
|
}
|
25540
24796
|
|
25541
|
-
const schemasElement = document.getElementById('schemas');
|
25542
|
-
const tablesElement = document.getElementById('tables');
|
25543
24797
|
const statsElement = document.getElementById('stats');
|
25544
24798
|
statsElement.innerHTML = statsHtml(null);
|
25545
24799
|
|
25546
24800
|
const columnsElement = document.getElementById('columns');
|
25547
24801
|
const indexesElement = document.getElementById('indexes');
|
25548
24802
|
|
25549
|
-
const schemaNames = Object.keys(window.metadata.schemas);
|
25550
24803
|
if (schemaNames.length === 1) {
|
25551
24804
|
schemasElement.style.display = 'none';
|
25552
24805
|
// TODO: duplicate code
|
25553
|
-
while (tablesElement.firstChild) {
|
25554
|
-
tablesElement.removeChild(tablesElement.firstChild);
|
25555
|
-
}
|
25556
24806
|
const schemaName = schemaNames[0];
|
25557
24807
|
const schema = window.metadata.schemas[schemaName];
|
25558
24808
|
const tableNames = Object.keys(schema.tables);
|
24809
|
+
|
25559
24810
|
tableNames.forEach(function (tableName) {
|
25560
24811
|
const optionElement = document.createElement('option');
|
25561
24812
|
optionElement.value = tableName;
|
25562
24813
|
optionElement.innerText = tableName;
|
25563
24814
|
tablesElement.appendChild(optionElement);
|
25564
24815
|
});
|
24816
|
+
if (tableNames.length > 0) {
|
24817
|
+
tablesElement.value = tableNames[0];
|
24818
|
+
}
|
25565
24819
|
} else {
|
25566
24820
|
schemasElement.style.display = 'flex';
|
24821
|
+
|
25567
24822
|
schemaNames.forEach(function (schemaName) {
|
25568
24823
|
const optionElement = document.createElement('option');
|
25569
24824
|
optionElement.value = schemaName;
|
25570
24825
|
optionElement.innerText = schemaName;
|
25571
24826
|
schemasElement.appendChild(optionElement);
|
25572
24827
|
});
|
24828
|
+
if (schemaNames.length > 0) {
|
24829
|
+
schemasElement.value = schemaNames[0];
|
24830
|
+
}
|
25573
24831
|
schemasElement.addEventListener('change', function () {
|
25574
24832
|
while (statsElement.firstChild) {
|
25575
24833
|
statsElement.removeChild(statsElement.firstChild);
|
@@ -25587,12 +24845,16 @@
|
|
25587
24845
|
const schemaName = schemasElement.value;
|
25588
24846
|
const schema = window.metadata.schemas[schemaName];
|
25589
24847
|
const tableNames = Object.keys(schema.tables);
|
24848
|
+
|
25590
24849
|
tableNames.forEach(function (tableName) {
|
25591
24850
|
const optionElement = document.createElement('option');
|
25592
24851
|
optionElement.value = tableName;
|
25593
24852
|
optionElement.innerText = tableName;
|
25594
24853
|
tablesElement.appendChild(optionElement);
|
25595
24854
|
});
|
24855
|
+
if (tableNames.length > 0) {
|
24856
|
+
tablesElement.value = tableNames[0];
|
24857
|
+
}
|
25596
24858
|
});
|
25597
24859
|
}
|
25598
24860
|
tablesElement.addEventListener('change', function () {
|
@@ -25654,10 +24916,20 @@
|
|
25654
24916
|
}
|
25655
24917
|
});
|
25656
24918
|
window.structureLoaded = true;
|
24919
|
+
|
24920
|
+
if (schemaNames.length === 1) {
|
24921
|
+
setTimeout(() => { tablesElement.focus(); }, 0);
|
24922
|
+
} else {
|
24923
|
+
setTimeout(() => { schemasElement.focus(); }, 0);
|
24924
|
+
}
|
24925
|
+
|
24926
|
+
tablesElement.dispatchEvent(new Event('change'));
|
25657
24927
|
}
|
25658
24928
|
|
25659
24929
|
function selectHelpTab () {
|
25660
|
-
document.getElementById('help-box')
|
24930
|
+
const helpBoxElement = document.getElementById('help-box');
|
24931
|
+
helpBoxElement.style.display = 'block';
|
24932
|
+
setTimeout(() => { helpBoxElement.focus(); }, 0);
|
25661
24933
|
}
|
25662
24934
|
|
25663
24935
|
function selectGraphTab (internal) {
|
@@ -25667,12 +24939,11 @@
|
|
25667
24939
|
document.getElementById('fetch-sql-box').style.display = 'none';
|
25668
24940
|
document.getElementById('cancel-button').style.visibility = 'hidden';
|
25669
24941
|
updateDownloadButtons(window?.sqlFetch);
|
25670
|
-
maybeFetchResult(internal);
|
25671
|
-
|
25672
24942
|
focus(getSelection());
|
24943
|
+
maybeFetchResult(internal);
|
25673
24944
|
}
|
25674
24945
|
|
25675
|
-
function
|
24946
|
+
function selectQueryTab (internal) {
|
25676
24947
|
document.getElementById('query-box').style.display = 'flex';
|
25677
24948
|
document.getElementById('submit-box').style.display = 'flex';
|
25678
24949
|
document.getElementById('result-box').style.display = 'flex';
|
@@ -25688,6 +24959,8 @@
|
|
25688
24959
|
});
|
25689
24960
|
|
25690
24961
|
const savedElement = document.getElementById('saved-box');
|
24962
|
+
setTimeout(() => { savedElement.focus(); }, 0);
|
24963
|
+
|
25691
24964
|
const saved = window.metadata.saved;
|
25692
24965
|
const numFiles = Object.keys(saved).length;
|
25693
24966
|
setStatus(`${numFiles} file${numFiles === 1 ? '' : 's'}`);
|
@@ -25721,7 +24994,6 @@
|
|
25721
24994
|
runLinkElement.href = runUrl.pathname + runUrl.search;
|
25722
24995
|
addEventListener(runLinkElement, 'click', (event) => {
|
25723
24996
|
clearResult();
|
25724
|
-
route(event.target, event, viewUrl, true);
|
25725
24997
|
route(event.target, event, runUrl, true);
|
25726
24998
|
});
|
25727
24999
|
|
@@ -25764,15 +25036,18 @@
|
|
25764
25036
|
if (!target || !event) {
|
25765
25037
|
throw new Error('you must specify target and event')
|
25766
25038
|
}
|
25767
|
-
|
25039
|
+
|
25040
|
+
window.lastSetSelectionValueFromUrlParam = null;
|
25041
|
+
window.lastEditorValueSet = null;
|
25042
|
+
|
25768
25043
|
const url = new URL(window.location);
|
25769
|
-
let sql =
|
25044
|
+
let sql = getEditorValue().trim();
|
25770
25045
|
sql = sql === '' ? null : sql;
|
25771
25046
|
|
25772
25047
|
url.searchParams.set('run', 'true');
|
25773
25048
|
|
25774
25049
|
if (url.searchParams.has('file')) {
|
25775
|
-
if (window.metadata.saved[url.searchParams.get('file')].contents !==
|
25050
|
+
if (window.metadata.saved[url.searchParams.get('file')].contents !== getEditorValue()) {
|
25776
25051
|
url.searchParams.delete('file');
|
25777
25052
|
url.searchParams.set('sql', sql);
|
25778
25053
|
}
|
@@ -25952,18 +25227,36 @@
|
|
25952
25227
|
const hasSqluiReferrer = document.referrer && new URL(document.referrer).origin === url.origin;
|
25953
25228
|
const variables = parseSqlVariables(params);
|
25954
25229
|
|
25230
|
+
if (params.has('file') && params.has('sql')) {
|
25231
|
+
// TODO: show an error.
|
25232
|
+
throw new Error('You can only specify a file or sql, not both.')
|
25233
|
+
}
|
25234
|
+
|
25955
25235
|
// Only allow auto-run if coming from another SQLUI page. The idea here is to let the app link to URLs with run=true
|
25956
25236
|
// but not other apps. This allows meta/shift-clicking to run a query.
|
25957
|
-
let run = false;
|
25958
25237
|
if (params.has('run')) {
|
25959
|
-
run = (internal || hasSqluiReferrer) && ['1', 'true'].includes(params.get('run')?.toLowerCase());
|
25960
25238
|
url.searchParams.delete('run');
|
25961
25239
|
window.history.replaceState({}, '', url);
|
25962
|
-
|
25240
|
+
clearResult();
|
25963
25241
|
|
25964
|
-
|
25965
|
-
|
25966
|
-
|
25242
|
+
if (!internal && !hasSqluiReferrer) {
|
25243
|
+
throw new Error('run only allowed for internal usage')
|
25244
|
+
}
|
25245
|
+
|
25246
|
+
if (params.has('sql') || params.has('file')) {
|
25247
|
+
const sqlFetch = buildSqlFetch(sql, file, variables, selection);
|
25248
|
+
setEditorValue(sqlFetch.sql);
|
25249
|
+
if (params.has('selection')) {
|
25250
|
+
window.lastSetSelectionValueFromUrlParam = selection;
|
25251
|
+
focus(selection);
|
25252
|
+
} else {
|
25253
|
+
window.lastSetSelectionValueFromUrlParam = null;
|
25254
|
+
}
|
25255
|
+
fetchSql(sqlFetch);
|
25256
|
+
return
|
25257
|
+
} else {
|
25258
|
+
throw new Error('run param specified without sql or file')
|
25259
|
+
}
|
25967
25260
|
}
|
25968
25261
|
|
25969
25262
|
const existingRequest = window.sqlFetch;
|
@@ -25975,7 +25268,7 @@
|
|
25975
25268
|
const queryMatches = sqlMatches || fileMatches;
|
25976
25269
|
if (selectionMatches && queryMatches && variablesMatch) {
|
25977
25270
|
displaySqlFetch(existingRequest);
|
25978
|
-
if (params.has('selection')) {
|
25271
|
+
if (params.has('selection') && window.lastSetSelectionValueFromUrlParam !== selection) {
|
25979
25272
|
focus(selection);
|
25980
25273
|
}
|
25981
25274
|
return
|
@@ -25985,13 +25278,12 @@
|
|
25985
25278
|
clearResult();
|
25986
25279
|
|
25987
25280
|
const sqlFetch = buildSqlFetch(sql, file, variables, selection);
|
25988
|
-
if (params.has('sql') || params.has('file')) {
|
25989
|
-
|
25990
|
-
if (run) {
|
25991
|
-
fetchSql(sqlFetch);
|
25992
|
-
}
|
25281
|
+
if ((params.has('sql') || params.has('file')) && !isLastEditorValueSet(sqlFetch.sql)) {
|
25282
|
+
setEditorValue(sqlFetch.sql);
|
25993
25283
|
}
|
25994
|
-
|
25284
|
+
|
25285
|
+
if (params.has('selection') && window.lastSetSelectionValueFromUrlParam !== selection) {
|
25286
|
+
window.lastSetSelectionValueFromUrlParam = selection;
|
25995
25287
|
focus(selection);
|
25996
25288
|
}
|
25997
25289
|
}
|
@@ -26173,7 +25465,7 @@
|
|
26173
25465
|
const row = parseInt(node.dataset.row);
|
26174
25466
|
const column = parseInt(node.dataset.column);
|
26175
25467
|
const title = window.sqlFetch.result.columns[column].replaceAll('\n', '¶');
|
26176
|
-
if (event.metaKey) {
|
25468
|
+
if (event.metaKey || event.ctrlKey) {
|
26177
25469
|
createPopup(title, window.sqlFetch.result.rows[row][column]);
|
26178
25470
|
} else if (event.altKey) {
|
26179
25471
|
copyTextToClipboard(window.sqlFetch.result.rows[row][column]);
|
@@ -26398,8 +25690,38 @@
|
|
26398
25690
|
});
|
26399
25691
|
|
26400
25692
|
document.addEventListener('keydown', (event) => {
|
25693
|
+
if (event.code === 'ControlLeft' || event.code === 'ControlRight') {
|
25694
|
+
Array.prototype.forEach.call(document.getElementsByClassName('keyboard-shortcut-indicator'), function (selected) {
|
25695
|
+
selected.style.visibility = 'visible';
|
25696
|
+
});
|
25697
|
+
}
|
25698
|
+
|
26401
25699
|
if (event.code === 'Escape') {
|
26402
25700
|
focus();
|
25701
|
+
return
|
25702
|
+
}
|
25703
|
+
|
25704
|
+
const isMac = navigator.userAgent.includes('Mac');
|
25705
|
+
if (isMac && event.code === 'Digit0' && event.ctrlKey) {
|
25706
|
+
document.getElementById('header-link').click();
|
25707
|
+
} else if (isMac && event.code === 'Digit1' && event.ctrlKey) {
|
25708
|
+
selectTab(event, 'query');
|
25709
|
+
} else if (isMac && event.code === 'Digit2' && event.ctrlKey) {
|
25710
|
+
selectTab(event, 'graph');
|
25711
|
+
} else if (isMac && event.code === 'Digit3' && event.ctrlKey) {
|
25712
|
+
selectTab(event, 'saved');
|
25713
|
+
} else if (isMac && event.code === 'Digit4' && event.ctrlKey) {
|
25714
|
+
selectTab(event, 'structure');
|
25715
|
+
} else if (isMac && event.code === 'Digit5' && event.ctrlKey) {
|
25716
|
+
selectTab(event, 'help');
|
25717
|
+
}
|
25718
|
+
});
|
25719
|
+
|
25720
|
+
document.addEventListener('keyup', (event) => {
|
25721
|
+
if ((event.code === 'ControlLeft' || event.code === 'ControlRight') && !event.ctrlKey) {
|
25722
|
+
Array.prototype.forEach.call(document.getElementsByClassName('keyboard-shortcut-indicator'), function (selected) {
|
25723
|
+
selected.style.visibility = 'hidden';
|
25724
|
+
});
|
26403
25725
|
}
|
26404
25726
|
});
|
26405
25727
|
|