sqlui 0.1.68 → 0.1.70

Sign up to get free protection for your applications and to get access to all the features.
@@ -9566,7 +9566,7 @@
9566
9566
  }
9567
9567
  });
9568
9568
  }
9569
- const baseTheme$1$3 = /*@__PURE__*/buildTheme("." + baseThemeID, {
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$3).reverse());
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$2];
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$2 = /*@__PURE__*/EditorView.baseTheme({
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$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$1 = /*@__PURE__*/EditorView.baseTheme({
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$1 = /*@__PURE__*/StateEffect.define();
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$1))
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$1.of(true),
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$1.of(false) });
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$1 = /*@__PURE__*/EditorView.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$1
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
- const wrapperElement = document.getElementById('popup-wrapper');
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) setSelection(selection);
24641
+ if (selection) {
24642
+ setSelection(selection);
24643
+ }
25407
24644
  }
25408
24645
 
25409
- function getValue () {
24646
+ function getEditorValue () {
25410
24647
  return window.editorView.state.doc.toString()
25411
24648
  }
25412
24649
 
25413
- function setValue (value) {
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
- selectResultTab(internal);
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').style.display = 'block';
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 selectResultTab (internal) {
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,10 +24994,15 @@
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
 
25000
+ const viewOnGithubLinkElement = document.createElement('a');
25001
+ viewOnGithubLinkElement.classList.add('link', 'view-github-link');
25002
+ viewOnGithubLinkElement.innerText = 'github';
25003
+ viewOnGithubLinkElement.href = file.github_url;
25004
+ viewOnGithubLinkElement.target = '_blank';
25005
+
25728
25006
  const nameElement = document.createElement('h2');
25729
25007
  nameElement.innerText = file.filename;
25730
25008
  nameElement.classList.add('name');
@@ -25733,6 +25011,7 @@
25733
25011
  linksElement.classList.add('links');
25734
25012
  linksElement.appendChild(viewLinkElement);
25735
25013
  linksElement.appendChild(runLinkElement);
25014
+ linksElement.appendChild(viewOnGithubLinkElement);
25736
25015
 
25737
25016
  const descriptionElement = document.createElement('p');
25738
25017
  descriptionElement.innerText = file.description;
@@ -25764,15 +25043,18 @@
25764
25043
  if (!target || !event) {
25765
25044
  throw new Error('you must specify target and event')
25766
25045
  }
25767
- clearResult();
25046
+
25047
+ window.lastSetSelectionValueFromUrlParam = null;
25048
+ window.lastEditorValueSet = null;
25049
+
25768
25050
  const url = new URL(window.location);
25769
- let sql = getValue().trim();
25051
+ let sql = getEditorValue().trim();
25770
25052
  sql = sql === '' ? null : sql;
25771
25053
 
25772
25054
  url.searchParams.set('run', 'true');
25773
25055
 
25774
25056
  if (url.searchParams.has('file')) {
25775
- if (window.metadata.saved[url.searchParams.get('file')].contents !== getValue()) {
25057
+ if (window.metadata.saved[url.searchParams.get('file')].contents !== getEditorValue()) {
25776
25058
  url.searchParams.delete('file');
25777
25059
  url.searchParams.set('sql', sql);
25778
25060
  }
@@ -25952,18 +25234,36 @@
25952
25234
  const hasSqluiReferrer = document.referrer && new URL(document.referrer).origin === url.origin;
25953
25235
  const variables = parseSqlVariables(params);
25954
25236
 
25237
+ if (params.has('file') && params.has('sql')) {
25238
+ // TODO: show an error.
25239
+ throw new Error('You can only specify a file or sql, not both.')
25240
+ }
25241
+
25955
25242
  // 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
25243
  // but not other apps. This allows meta/shift-clicking to run a query.
25957
- let run = false;
25958
25244
  if (params.has('run')) {
25959
- run = (internal || hasSqluiReferrer) && ['1', 'true'].includes(params.get('run')?.toLowerCase());
25960
25245
  url.searchParams.delete('run');
25961
25246
  window.history.replaceState({}, '', url);
25962
- }
25247
+ clearResult();
25963
25248
 
25964
- if (params.has('file') && params.has('sql')) {
25965
- // TODO: show an error.
25966
- throw new Error('You can only specify a file or sql, not both.')
25249
+ if (!internal && !hasSqluiReferrer) {
25250
+ throw new Error('run only allowed for internal usage')
25251
+ }
25252
+
25253
+ if (params.has('sql') || params.has('file')) {
25254
+ const sqlFetch = buildSqlFetch(sql, file, variables, selection);
25255
+ setEditorValue(sqlFetch.sql);
25256
+ if (params.has('selection')) {
25257
+ window.lastSetSelectionValueFromUrlParam = selection;
25258
+ focus(selection);
25259
+ } else {
25260
+ window.lastSetSelectionValueFromUrlParam = null;
25261
+ }
25262
+ fetchSql(sqlFetch);
25263
+ return
25264
+ } else {
25265
+ throw new Error('run param specified without sql or file')
25266
+ }
25967
25267
  }
25968
25268
 
25969
25269
  const existingRequest = window.sqlFetch;
@@ -25975,7 +25275,7 @@
25975
25275
  const queryMatches = sqlMatches || fileMatches;
25976
25276
  if (selectionMatches && queryMatches && variablesMatch) {
25977
25277
  displaySqlFetch(existingRequest);
25978
- if (params.has('selection')) {
25278
+ if (params.has('selection') && window.lastSetSelectionValueFromUrlParam !== selection) {
25979
25279
  focus(selection);
25980
25280
  }
25981
25281
  return
@@ -25985,13 +25285,12 @@
25985
25285
  clearResult();
25986
25286
 
25987
25287
  const sqlFetch = buildSqlFetch(sql, file, variables, selection);
25988
- if (params.has('sql') || params.has('file')) {
25989
- setValue(sqlFetch.sql);
25990
- if (run) {
25991
- fetchSql(sqlFetch);
25992
- }
25288
+ if ((params.has('sql') || params.has('file')) && !isLastEditorValueSet(sqlFetch.sql)) {
25289
+ setEditorValue(sqlFetch.sql);
25993
25290
  }
25994
- if (params.has('selection')) {
25291
+
25292
+ if (params.has('selection') && window.lastSetSelectionValueFromUrlParam !== selection) {
25293
+ window.lastSetSelectionValueFromUrlParam = selection;
25995
25294
  focus(selection);
25996
25295
  }
25997
25296
  }
@@ -26173,7 +25472,7 @@
26173
25472
  const row = parseInt(node.dataset.row);
26174
25473
  const column = parseInt(node.dataset.column);
26175
25474
  const title = window.sqlFetch.result.columns[column].replaceAll('\n', '¶');
26176
- if (event.metaKey) {
25475
+ if (event.metaKey || event.ctrlKey) {
26177
25476
  createPopup(title, window.sqlFetch.result.rows[row][column]);
26178
25477
  } else if (event.altKey) {
26179
25478
  copyTextToClipboard(window.sqlFetch.result.rows[row][column]);
@@ -26398,8 +25697,38 @@
26398
25697
  });
26399
25698
 
26400
25699
  document.addEventListener('keydown', (event) => {
25700
+ if (event.code === 'ControlLeft' || event.code === 'ControlRight') {
25701
+ Array.prototype.forEach.call(document.getElementsByClassName('keyboard-shortcut-indicator'), function (selected) {
25702
+ selected.style.visibility = 'visible';
25703
+ });
25704
+ }
25705
+
26401
25706
  if (event.code === 'Escape') {
26402
25707
  focus();
25708
+ return
25709
+ }
25710
+
25711
+ const isMac = navigator.userAgent.includes('Mac');
25712
+ if (isMac && event.code === 'Digit0' && event.ctrlKey) {
25713
+ document.getElementById('header-link').click();
25714
+ } else if (isMac && event.code === 'Digit1' && event.ctrlKey) {
25715
+ selectTab(event, 'query');
25716
+ } else if (isMac && event.code === 'Digit2' && event.ctrlKey) {
25717
+ selectTab(event, 'graph');
25718
+ } else if (isMac && event.code === 'Digit3' && event.ctrlKey) {
25719
+ selectTab(event, 'saved');
25720
+ } else if (isMac && event.code === 'Digit4' && event.ctrlKey) {
25721
+ selectTab(event, 'structure');
25722
+ } else if (isMac && event.code === 'Digit5' && event.ctrlKey) {
25723
+ selectTab(event, 'help');
25724
+ }
25725
+ });
25726
+
25727
+ document.addEventListener('keyup', (event) => {
25728
+ if ((event.code === 'ControlLeft' || event.code === 'ControlRight') && !event.ctrlKey) {
25729
+ Array.prototype.forEach.call(document.getElementsByClassName('keyboard-shortcut-indicator'), function (selected) {
25730
+ selected.style.visibility = 'hidden';
25731
+ });
26403
25732
  }
26404
25733
  });
26405
25734