sqlui 0.1.31 → 0.1.32

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 177d85d52d1111b7db8d5c729c01a47eb3ae0a2e9b8e3b1a20c8e536870917a3
4
- data.tar.gz: 5d45fe6194c93b9390be9f269e0ace2ef1b48554246e3442ad318b554368853a
3
+ metadata.gz: 7e17fe02caa80d2ea8ff8a7fc85ed11f4127526aeaec4c80f99de5b2dc23c9fc
4
+ data.tar.gz: 03b85e9805bf65329a48ba2f25712982e73e52c6beacffe0f561f75097827194
5
5
  SHA512:
6
- metadata.gz: 2edd639fd3c23d1f1e63a09724a5c9c17e3d636839ac60a3a53d99c972b6a01a54b6c953b56bbd77fc0afce88d00dd46bb23eb18cec8accad443157a1366e268
7
- data.tar.gz: 1321bff98b50d4cd5aabe5e88f9b364dc0ec3bc57c881b0fe9c8bda358f5b24e96547b2ee8f0592d1b9ea75535da4f39c38d1f066327f0e3647a278c7ede10e1
6
+ metadata.gz: c93782f85fc36265a469a249446f60417463e8051af9f54b401d501090c03ce5b226deb0a1999148e4bcdd2ca89ccc15f906c4d8705e305da069cdd49844f5a1
7
+ data.tar.gz: 50f397871d5262dc1a9d7a555a5e3d233cf4d4e8b747200a8723905f0ef07bda390319353ebafa15b3a58f25849a82406b3c0f09131d7d4a8c303563f7a22f7a
data/.version CHANGED
@@ -1 +1 @@
1
- 0.1.31
1
+ 0.1.32
data/app/server.rb CHANGED
@@ -40,14 +40,14 @@ class Server < Sinatra::Base
40
40
  get "#{database.url_path}/sqlui.css" do
41
41
  @css ||= File.read(File.join(resources_dir, 'sqlui.css'))
42
42
  status 200
43
- headers 'Content-Type' => 'text/css'
43
+ headers 'Content-Type' => 'text/css; charset=utf-8'
44
44
  body @css
45
45
  end
46
46
 
47
47
  get "#{database.url_path}/sqlui.js" do
48
48
  @js ||= File.read(File.join(resources_dir, 'sqlui.js'))
49
49
  status 200
50
- headers 'Content-Type' => 'text/javascript'
50
+ headers 'Content-Type' => 'text/javascript; charset=utf-8'
51
51
  body @js
52
52
  end
53
53
 
@@ -76,7 +76,7 @@ class Server < Sinatra::Base
76
76
  }
77
77
  end
78
78
  status 200
79
- headers 'Content-Type' => 'application/json'
79
+ headers 'Content-Type' => 'application/json; charset=utf-8'
80
80
  body metadata.to_json
81
81
  end
82
82
 
@@ -117,23 +117,22 @@ class Server < Sinatra::Base
117
117
  result[:query] = full_sql
118
118
 
119
119
  status 200
120
- headers 'Content-Type' => 'application/json'
120
+ headers 'Content-Type' => 'application/json; charset=utf-8'
121
121
  body result.to_json
122
122
  end
123
123
 
124
124
  get(%r{#{Regexp.escape(database.url_path)}/(query|graph|structure|saved)}) do
125
125
  @html ||= File.read(File.join(resources_dir, 'sqlui.html'))
126
126
  status 200
127
- headers 'Content-Type' => 'text/html'
127
+ headers 'Content-Type' => 'text/html; charset=utf-8'
128
128
  body @html
129
129
  end
130
130
  end
131
131
 
132
132
  error do |e|
133
133
  status 500
134
- headers 'Content-Type' => 'application/json'
134
+ headers 'Content-Type' => 'application/json; charset=utf-8'
135
135
  message = e.message.lines.first&.strip || 'unexpected error'
136
- message = "#{message[0..80]}…" if message.length > 80
137
136
  result = {
138
137
  error: message,
139
138
  stacktrace: e.backtrace.map { |b| b }.join("\n")
@@ -148,7 +147,7 @@ class Server < Sinatra::Base
148
147
 
149
148
  def client_error(message, stacktrace: nil)
150
149
  status(400)
151
- headers 'Content-Type' => 'application/json'
150
+ headers 'Content-Type' => 'application/json; charset=utf-8'
152
151
  body({ error: message, stacktrace: stacktrace }.compact.to_json)
153
152
  end
154
153
 
@@ -1,5 +1,6 @@
1
1
  <html lang="en">
2
2
  <head>
3
+ <meta charset="utf-8">
3
4
  <title>SQLUI <%= config.name %> Databases</title>
4
5
 
5
6
  <style>
@@ -1,70 +1,71 @@
1
- <head>
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="utf-8">
4
+ <title>SQLUI</title>
5
+ <script src="sqlui.js"></script>
6
+ <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
7
+ <link rel="stylesheet" href="sqlui.css">
8
+ </head>
2
9
 
3
- <title>SQLUI</title>
4
-
5
- <script src="sqlui.js"></script>
6
- <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
7
- <link rel="stylesheet" href="sqlui.css">
8
- </head>
9
-
10
- <body>
11
- <div id="loading-box" class="loading-box">
12
- </div>
13
-
14
- <div id="main-box" class="main-box" style="display:none">
15
- <div class="tabs-box">
16
- <h1 class="header"><a id="header-link">SQLUI</a></h1>
17
- <h1 id="server-name" class="server-name"></h1>
18
- <a id="query-tab-button" class="tab-button">Query</a>
19
- <a id="graph-tab-button" class="tab-button">Graph</a>
20
- <a id="saved-tab-button" class="tab-button">Saved</a>
21
- <a id="structure-tab-button" class="tab-button">Structure</a>
10
+ <body>
11
+ <div id="loading-box" class="loading-box">
22
12
  </div>
23
13
 
24
- <div id="query-box" class="query-box tab-content-element graph-element query-element" style="display: none;">
25
- <div id="query" class="query"></div>
26
- </div>
14
+ <div id="main-box" class="main-box" style="display:none">
15
+ <div class="tabs-box">
16
+ <h1 class="header"><a id="header-link">SQLUI</a></h1>
17
+ <h1 id="server-name" class="server-name"></h1>
18
+ <a id="query-tab-button" class="tab-button">Query</a>
19
+ <a id="graph-tab-button" class="tab-button">Graph</a>
20
+ <a id="saved-tab-button" class="tab-button">Saved</a>
21
+ <a id="structure-tab-button" class="tab-button">Structure</a>
22
+ </div>
27
23
 
28
- <div id="submit-box" class="submit-box tab-content-element graph-element query-element" style="display: none;">
29
- <input id="cancel-button" class="submit-button" type="button" value="cancel"></input>
30
- <div class="submit-fill"></div>
31
- <input id="submit-current-button" class="submit-button" type="button" value="run selection (ctrl-enter)"></input>
32
- <input id="submit-all-button" class="submit-button" type="button" value="run (ctrl-shift-enter)"></input>
33
- </div>
24
+ <div id="query-box" class="query-box tab-content-element graph-element query-element" style="display: none;">
25
+ <div id="query" class="query"></div>
26
+ </div>
34
27
 
35
- <div id="result-box" class="result-box tab-content-element query-element" style="display: none;">
36
- </div>
28
+ <div id="submit-box" class="submit-box tab-content-element graph-element query-element" style="display: none;">
29
+ <input id="cancel-button" class="submit-button" type="button" value="cancel"></input>
30
+ <div class="submit-fill"></div>
31
+ <input id="submit-current-button" class="submit-button" type="button" value="run selection (ctrl-enter)"></input>
32
+ <input id="submit-all-button" class="submit-button" type="button" value="run (ctrl-shift-enter)"></input>
33
+ </div>
37
34
 
38
- <div id="graph-box" class="graph-box tab-content-element graph-element" style="display: none;">
39
- </div>
35
+ <div id="result-box" class="result-box tab-content-element query-element" style="display: none;">
36
+ </div>
40
37
 
41
- <div id="fetch-sql-box" class="fetch-sql-box tab-content-element graph-element query-element" style="display: none;">
42
- <div id="result-loader" class="loader"></div>
43
- <p id="result-time" class="result-time"></p>
44
- </div>
38
+ <div id="graph-box" class="graph-box tab-content-element graph-element" style="display: none;">
39
+ </div>
45
40
 
46
- <div id="saved-box" class="saved-box tab-content-element saved-element" style="display: none;">
47
- </div>
41
+ <div id="fetch-sql-box" class="fetch-sql-box tab-content-element graph-element query-element" style="display: none;">
42
+ <div id="result-loader" class="loader"></div>
43
+ <p id="result-time" class="result-time"></p>
44
+ </div>
48
45
 
49
- <div id="structure-box" class="structure-box tab-content-element structure-element" style="display: none;">
50
- <div style="display: flex; flex: 1; flex-direction: row; align-items: stretch;">
51
- <select id="schemas" class="schemas" size="4">
52
- </select>
53
- <select id="tables" class="tables" size="4">
54
- </select>
55
- <div id="table-info" class="table-info">
56
- <div id="columns" class="columns">
57
- </div>
58
- <div id="indexes" class="indexes">
46
+ <div id="saved-box" class="saved-box tab-content-element saved-element" style="display: none;">
47
+ </div>
48
+
49
+ <div id="structure-box" class="structure-box tab-content-element structure-element" style="display: none;">
50
+ <div style="display: flex; flex: 1; flex-direction: row; align-items: stretch;">
51
+ <select id="schemas" class="schemas" size="4">
52
+ </select>
53
+ <select id="tables" class="tables" size="4">
54
+ </select>
55
+ <div id="table-info" class="table-info">
56
+ <div id="columns" class="columns">
57
+ </div>
58
+ <div id="indexes" class="indexes">
59
+ </div>
59
60
  </div>
60
61
  </div>
61
62
  </div>
62
- </div>
63
63
 
64
- <div id="status-box" class="status-box">
65
- <div id="result-status" class="status tab-content-element query-element"></div>
66
- <div id="graph-status" class="status tab-content-element graph-element"></div>
67
- <div id="saved-status" class="status tab-content-element saved-element"></div>
64
+ <div id="status-box" class="status-box">
65
+ <div id="result-status" class="status tab-content-element query-element"></div>
66
+ <div id="graph-status" class="status tab-content-element graph-element"></div>
67
+ <div id="saved-status" class="status tab-content-element saved-element"></div>
68
+ </div>
68
69
  </div>
69
- </div>
70
- </body>
70
+ </body>
71
+ </html>
@@ -15413,8 +15413,13 @@
15413
15413
  The [language data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) facet
15414
15414
  used for this language.
15415
15415
  */
15416
- data, parser, extraExtensions = []) {
15416
+ data, parser, extraExtensions = [],
15417
+ /**
15418
+ A language name.
15419
+ */
15420
+ name = "") {
15417
15421
  this.data = data;
15422
+ this.name = name;
15418
15423
  // Kludge to define EditorState.tree as a debugging helper,
15419
15424
  // without the EditorState package actually knowing about
15420
15425
  // languages and lezer trees.
@@ -15502,8 +15507,8 @@
15502
15507
  parsers.
15503
15508
  */
15504
15509
  class LRLanguage extends Language {
15505
- constructor(data, parser) {
15506
- super(data, parser);
15510
+ constructor(data, parser, name) {
15511
+ super(data, parser, [], name);
15507
15512
  this.parser = parser;
15508
15513
  }
15509
15514
  /**
@@ -15513,14 +15518,14 @@
15513
15518
  let data = defineLanguageFacet(spec.languageData);
15514
15519
  return new LRLanguage(data, spec.parser.configure({
15515
15520
  props: [languageDataProp.add(type => type.isTop ? data : undefined)]
15516
- }));
15521
+ }), spec.name);
15517
15522
  }
15518
15523
  /**
15519
15524
  Create a new instance of this language with a reconfigured
15520
- version of its parser.
15525
+ version of its parser and optionally a new name.
15521
15526
  */
15522
- configure(options) {
15523
- return new LRLanguage(this.data, this.parser.configure(options));
15527
+ configure(options, name) {
15528
+ return new LRLanguage(this.data, this.parser.configure(options), name || this.name);
15524
15529
  }
15525
15530
  get allowsNesting() { return this.parser.hasWrappers(); }
15526
15531
  }
@@ -15821,14 +15826,14 @@
15821
15826
  // state updates with parse work beyond the viewport.
15822
15827
  let upto = this.context.treeLen == tr.startState.doc.length ? undefined
15823
15828
  : Math.max(tr.changes.mapPos(this.context.treeLen), newCx.viewport.to);
15824
- if (!newCx.work(20 /* Apply */, upto))
15829
+ if (!newCx.work(20 /* Work.Apply */, upto))
15825
15830
  newCx.takeTree();
15826
15831
  return new LanguageState(newCx);
15827
15832
  }
15828
15833
  static init(state) {
15829
- let vpTo = Math.min(3000 /* InitViewport */, state.doc.length);
15834
+ let vpTo = Math.min(3000 /* Work.InitViewport */, state.doc.length);
15830
15835
  let parseState = ParseContext.create(state.facet(language).parser, state, { from: 0, to: vpTo });
15831
- if (!parseState.work(20 /* Apply */, vpTo))
15836
+ if (!parseState.work(20 /* Work.Apply */, vpTo))
15832
15837
  parseState.takeTree();
15833
15838
  return new LanguageState(parseState);
15834
15839
  }
@@ -15845,14 +15850,14 @@
15845
15850
  }
15846
15851
  });
15847
15852
  let requestIdle = (callback) => {
15848
- let timeout = setTimeout(() => callback(), 500 /* MaxPause */);
15853
+ let timeout = setTimeout(() => callback(), 500 /* Work.MaxPause */);
15849
15854
  return () => clearTimeout(timeout);
15850
15855
  };
15851
15856
  if (typeof requestIdleCallback != "undefined")
15852
15857
  requestIdle = (callback) => {
15853
15858
  let idle = -1, timeout = setTimeout(() => {
15854
- idle = requestIdleCallback(callback, { timeout: 500 /* MaxPause */ - 100 /* MinPause */ });
15855
- }, 100 /* MinPause */);
15859
+ idle = requestIdleCallback(callback, { timeout: 500 /* Work.MaxPause */ - 100 /* Work.MinPause */ });
15860
+ }, 100 /* Work.MinPause */);
15856
15861
  return () => idle < 0 ? clearTimeout(timeout) : cancelIdleCallback(idle);
15857
15862
  };
15858
15863
  const isInputPending = typeof navigator != "undefined" && ((_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending)
@@ -15875,7 +15880,7 @@
15875
15880
  this.scheduleWork();
15876
15881
  if (update.docChanged) {
15877
15882
  if (this.view.hasFocus)
15878
- this.chunkBudget += 50 /* ChangeBonus */;
15883
+ this.chunkBudget += 50 /* Work.ChangeBonus */;
15879
15884
  this.scheduleWork();
15880
15885
  }
15881
15886
  this.checkAsyncSchedule(cx);
@@ -15891,19 +15896,19 @@
15891
15896
  this.working = null;
15892
15897
  let now = Date.now();
15893
15898
  if (this.chunkEnd < now && (this.chunkEnd < 0 || this.view.hasFocus)) { // Start a new chunk
15894
- this.chunkEnd = now + 30000 /* ChunkTime */;
15895
- this.chunkBudget = 3000 /* ChunkBudget */;
15899
+ this.chunkEnd = now + 30000 /* Work.ChunkTime */;
15900
+ this.chunkBudget = 3000 /* Work.ChunkBudget */;
15896
15901
  }
15897
15902
  if (this.chunkBudget <= 0)
15898
15903
  return; // No more budget
15899
15904
  let { state, viewport: { to: vpTo } } = this.view, field = state.field(Language.state);
15900
- if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* MaxParseAhead */))
15905
+ if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* Work.MaxParseAhead */))
15901
15906
  return;
15902
- let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Slice */, deadline && !isInputPending ? Math.max(25 /* MinSlice */, deadline.timeRemaining() - 5) : 1e9);
15907
+ let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Work.Slice */, deadline && !isInputPending ? Math.max(25 /* Work.MinSlice */, deadline.timeRemaining() - 5) : 1e9);
15903
15908
  let viewportFirst = field.context.treeLen < vpTo && state.doc.length > vpTo + 1000;
15904
15909
  let done = field.context.work(() => {
15905
15910
  return isInputPending && isInputPending() || Date.now() > endTime;
15906
- }, vpTo + (viewportFirst ? 0 : 100000 /* MaxParseAhead */));
15911
+ }, vpTo + (viewportFirst ? 0 : 100000 /* Work.MaxParseAhead */));
15907
15912
  this.chunkBudget -= Date.now() - now;
15908
15913
  if (done || this.chunkBudget <= 0) {
15909
15914
  field.context.takeTree();
@@ -15941,7 +15946,14 @@
15941
15946
  */
15942
15947
  const language = /*@__PURE__*/Facet.define({
15943
15948
  combine(languages) { return languages.length ? languages[0] : null; },
15944
- enables: [Language.state, parseWorker]
15949
+ enables: language => [
15950
+ Language.state,
15951
+ parseWorker,
15952
+ EditorView.contentAttributes.compute([language], state => {
15953
+ let lang = state.facet(language);
15954
+ return lang && lang.name ? { "data-language": lang.name } : {};
15955
+ })
15956
+ ]
15945
15957
  });
15946
15958
  /**
15947
15959
  This class bundles a [language](https://codemirror.net/6/docs/ref/#language.Language) with an
@@ -15974,8 +15986,10 @@
15974
15986
 
15975
15987
  /**
15976
15988
  Facet that defines a way to provide a function that computes the
15977
- appropriate indentation depth at the start of a given line, or
15978
- `null` to indicate no appropriate indentation could be determined.
15989
+ appropriate indentation depth, as a column number (see
15990
+ [`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)), at the start of a given
15991
+ line, or `null` to indicate no appropriate indentation could be
15992
+ determined.
15979
15993
  */
15980
15994
  const indentService = /*@__PURE__*/Facet.define();
15981
15995
  /**
@@ -16020,12 +16034,13 @@
16020
16034
  return result;
16021
16035
  }
16022
16036
  /**
16023
- Get the indentation at the given position. Will first consult any
16024
- [indent services](https://codemirror.net/6/docs/ref/#language.indentService) that are registered,
16025
- and if none of those return an indentation, this will check the
16026
- syntax tree for the [indent node prop](https://codemirror.net/6/docs/ref/#language.indentNodeProp)
16027
- and use that if found. Returns a number when an indentation could
16028
- be determined, and null otherwise.
16037
+ Get the indentation, as a column number, at the given position.
16038
+ Will first consult any [indent services](https://codemirror.net/6/docs/ref/#language.indentService)
16039
+ that are registered, and if none of those return an indentation,
16040
+ this will check the syntax tree for the [indent node
16041
+ prop](https://codemirror.net/6/docs/ref/#language.indentNodeProp) and use that if found. Returns a
16042
+ number when an indentation could be determined, and null
16043
+ otherwise.
16029
16044
  */
16030
16045
  function getIndentation(context, pos) {
16031
16046
  if (context instanceof EditorState)
@@ -16135,8 +16150,9 @@
16135
16150
  /**
16136
16151
  A syntax tree node prop used to associate indentation strategies
16137
16152
  with node types. Such a strategy is a function from an indentation
16138
- context to a column number or null, where null indicates that no
16139
- definitive indentation can be determined.
16153
+ context to a column number (see also
16154
+ [`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)) or null, where null
16155
+ indicates that no definitive indentation can be determined.
16140
16156
  */
16141
16157
  const indentNodeProp = /*@__PURE__*/new NodeProp();
16142
16158
  // Compute the indentation for a given position from the syntax tree.
@@ -16692,7 +16708,12 @@
16692
16708
  [tags](https://lezer.codemirror.net/docs/ref#highlight.Tag).
16693
16709
  */
16694
16710
  class HighlightStyle {
16695
- constructor(spec, options) {
16711
+ constructor(
16712
+ /**
16713
+ The tag styles used to create this highlight style.
16714
+ */
16715
+ specs, options) {
16716
+ this.specs = specs;
16696
16717
  let modSpec;
16697
16718
  function def(spec) {
16698
16719
  let cls = StyleModule.newName();
@@ -16703,7 +16724,7 @@
16703
16724
  const scopeOpt = options.scope;
16704
16725
  this.scope = scopeOpt instanceof Language ? (type) => type.prop(languageDataProp) == scopeOpt.data
16705
16726
  : scopeOpt ? (type) => type == scopeOpt : undefined;
16706
- this.style = tagHighlighter(spec.map(style => ({
16727
+ this.style = tagHighlighter(specs.map(style => ({
16707
16728
  tag: style.tag,
16708
16729
  class: style.class || def(Object.assign({}, style, { tag: null }))
16709
16730
  })), {
@@ -21577,74 +21598,6 @@
21577
21598
  }
21578
21599
  });
21579
21600
 
21580
- // (The superfluous function calls around the list of extensions work
21581
- // around current limitations in tree-shaking software.)
21582
- /**
21583
- This is an extension value that just pulls together a number of
21584
- extensions that you might want in a basic editor. It is meant as a
21585
- convenient helper to quickly set up CodeMirror without installing
21586
- and importing a lot of separate packages.
21587
-
21588
- Specifically, it includes...
21589
-
21590
- - [the default command bindings](https://codemirror.net/6/docs/ref/#commands.defaultKeymap)
21591
- - [line numbers](https://codemirror.net/6/docs/ref/#view.lineNumbers)
21592
- - [special character highlighting](https://codemirror.net/6/docs/ref/#view.highlightSpecialChars)
21593
- - [the undo history](https://codemirror.net/6/docs/ref/#commands.history)
21594
- - [a fold gutter](https://codemirror.net/6/docs/ref/#language.foldGutter)
21595
- - [custom selection drawing](https://codemirror.net/6/docs/ref/#view.drawSelection)
21596
- - [drop cursor](https://codemirror.net/6/docs/ref/#view.dropCursor)
21597
- - [multiple selections](https://codemirror.net/6/docs/ref/#state.EditorState^allowMultipleSelections)
21598
- - [reindentation on input](https://codemirror.net/6/docs/ref/#language.indentOnInput)
21599
- - [the default highlight style](https://codemirror.net/6/docs/ref/#language.defaultHighlightStyle) (as fallback)
21600
- - [bracket matching](https://codemirror.net/6/docs/ref/#language.bracketMatching)
21601
- - [bracket closing](https://codemirror.net/6/docs/ref/#autocomplete.closeBrackets)
21602
- - [autocompletion](https://codemirror.net/6/docs/ref/#autocomplete.autocompletion)
21603
- - [rectangular selection](https://codemirror.net/6/docs/ref/#view.rectangularSelection) and [crosshair cursor](https://codemirror.net/6/docs/ref/#view.crosshairCursor)
21604
- - [active line highlighting](https://codemirror.net/6/docs/ref/#view.highlightActiveLine)
21605
- - [active line gutter highlighting](https://codemirror.net/6/docs/ref/#view.highlightActiveLineGutter)
21606
- - [selection match highlighting](https://codemirror.net/6/docs/ref/#search.highlightSelectionMatches)
21607
- - [search](https://codemirror.net/6/docs/ref/#search.searchKeymap)
21608
- - [linting](https://codemirror.net/6/docs/ref/#lint.lintKeymap)
21609
-
21610
- (You'll probably want to add some language package to your setup
21611
- too.)
21612
-
21613
- This extension does not allow customization. The idea is that,
21614
- once you decide you want to configure your editor more precisely,
21615
- you take this package's source (which is just a bunch of imports
21616
- and an array literal), copy it into your own code, and adjust it
21617
- as desired.
21618
- */
21619
- const basicSetup = /*@__PURE__*/(() => [
21620
- lineNumbers(),
21621
- highlightActiveLineGutter(),
21622
- highlightSpecialChars(),
21623
- history(),
21624
- foldGutter(),
21625
- drawSelection(),
21626
- dropCursor(),
21627
- EditorState.allowMultipleSelections.of(true),
21628
- indentOnInput(),
21629
- syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
21630
- bracketMatching(),
21631
- closeBrackets(),
21632
- autocompletion(),
21633
- rectangularSelection(),
21634
- crosshairCursor(),
21635
- highlightActiveLine(),
21636
- highlightSelectionMatches(),
21637
- keymap.of([
21638
- ...closeBracketsKeymap,
21639
- ...defaultKeymap,
21640
- ...searchKeymap,
21641
- ...historyKeymap,
21642
- ...foldKeymap,
21643
- ...completionKeymap,
21644
- ...lintKeymap
21645
- ])
21646
- ])();
21647
-
21648
21601
  /// A parse stack. These are used internally by the parser to track
21649
21602
  /// parsing progress. They also provide some properties and methods
21650
21603
  /// that external code such as a tokenizer can use to get information
@@ -23847,6 +23800,25 @@
23847
23800
  The standard SQL dialect.
23848
23801
  */
23849
23802
  const StandardSQL = /*@__PURE__*/SQLDialect.define({});
23803
+ const MySQLKeywords = "accessible algorithm analyze asensitive authors auto_increment autocommit avg avg_row_length binlog btree cache catalog_name chain change changed checkpoint checksum class_origin client_statistics coalesce code collations columns comment committed completion concurrent consistent contains contributors convert database databases day_hour day_microsecond day_minute day_second delay_key_write delayed delimiter des_key_file dev_pop dev_samp deviance directory disable discard distinctrow div dual dumpfile enable enclosed ends engine engines enum errors escaped even event events every explain extended fast field fields flush force found_rows fulltext grants handler hash high_priority hosts hour_microsecond hour_minute hour_second ignore ignore_server_ids import index index_statistics infile innodb insensitive insert_method install invoker iterate keys kill linear lines list load lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modify mutex mysql_errno no_write_to_binlog offline offset one online optimize optionally outfile pack_keys parser partition partitions password phase plugin plugins prev processlist profile profiles purge query quick range read_write rebuild recover regexp relaylog remove rename reorganize repair repeatable replace require resume rlike row_format rtree schedule schema_name schemas second_microsecond security sensitive separator serializable server share show slave slow snapshot soname spatial sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result ssl starting starts std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace terminated triggers truncate uncommitted uninstall unlock upgrade use use_frm user_resources user_statistics utc_date utc_time utc_timestamp variables views warnings xa xor year_month zerofill";
23804
+ const MySQLTypes = SQLTypes + "bool blob long longblob longtext medium mediumblob mediumint mediumtext tinyblob tinyint tinytext text bigint int1 int2 int3 int4 int8 float4 float8 varbinary varcharacter precision datetime unsigned signed";
23805
+ const MySQLBuiltin = "charset clear edit ego help nopager notee nowarning pager print prompt quit rehash source status system tee";
23806
+ /**
23807
+ [MySQL](https://dev.mysql.com/) dialect.
23808
+ */
23809
+ const MySQL = /*@__PURE__*/SQLDialect.define({
23810
+ operatorChars: "*+-%<>!=&|^",
23811
+ charSetCasts: true,
23812
+ doubleQuotedStrings: true,
23813
+ unquotedBitLiterals: true,
23814
+ hashComments: true,
23815
+ spaceAfterDashes: true,
23816
+ specialVar: "@?",
23817
+ identifierQuotes: "`",
23818
+ keywords: SQLKeywords + "group_concat " + MySQLKeywords,
23819
+ types: MySQLTypes,
23820
+ builtin: MySQLBuiltin
23821
+ });
23850
23822
 
23851
23823
  /* global google */
23852
23824
 
@@ -23873,20 +23845,83 @@
23873
23845
  clearResult();
23874
23846
  });
23875
23847
 
23848
+ const isMac = navigator.userAgent.includes('Mac');
23849
+ document.getElementById('submit-current-button').value = `run selection (${isMac ? '⌘' : 'Ctrl'}-Shift-Enter)`;
23850
+ document.getElementById('submit-all-button').value = `run (${isMac ? '⌘' : 'Ctrl'}-Shift-Enter)`;
23851
+
23876
23852
  const fixedHeightEditor = EditorView.theme({
23877
- '.cm-scroller': { height: '200px', overflow: 'auto', resize: 'vertical' }
23853
+ '.cm-scroller': {
23854
+ height: '200px',
23855
+ overflow: 'auto',
23856
+ resize: 'vertical'
23857
+ }
23858
+ });
23859
+ const schemas = Object.entries(window.metadata.schemas);
23860
+ const editorSchema = {};
23861
+ schemas.forEach(([schemaName, schema]) => {
23862
+ Object.entries(schema.tables).forEach(([tableName, table]) => {
23863
+ const qualifiedTableName = schemas.length === 1 ? tableName : `${schemaName}.${tableName}`;
23864
+ editorSchema[qualifiedTableName] = Object.keys(table.columns);
23865
+ });
23866
+ });
23867
+ // I prefer to use Cmd-Enter/Ctrl-Enter to submit the query. Here I am replacing the default mapping.
23868
+ // See https://codemirror.net/docs/ref/#commands.defaultKeymap
23869
+ // See https://github.com/codemirror/commands/blob/6aa9989f38fe3c7dbc9b72c5015a3db97370c07a/src/commands.ts#L891
23870
+ const customDefaultKeymap = defaultKeymap.map(keymap => {
23871
+ if (keymap.key === 'Mod-Enter') {
23872
+ keymap.key = 'Shift-Enter';
23873
+ }
23874
+ return keymap
23878
23875
  });
23876
+ const editorKeymap = keymap.of([
23877
+ {
23878
+ key: 'Cmd-Enter',
23879
+ run: onSubmit,
23880
+ preventDefault: true,
23881
+ shift: onShiftSubmit
23882
+ },
23883
+ {
23884
+ key: 'Ctrl-Enter',
23885
+ run: onSubmit,
23886
+ preventDefault: true,
23887
+ shift: onShiftSubmit
23888
+ },
23889
+ ...closeBracketsKeymap,
23890
+ ...customDefaultKeymap,
23891
+ ...searchKeymap,
23892
+ ...historyKeymap,
23893
+ ...foldKeymap,
23894
+ ...completionKeymap,
23895
+ ...lintKeymap
23896
+ ]);
23879
23897
  window.editorView = new EditorView({
23880
23898
  state: EditorState.create({
23881
23899
  extensions: [
23882
- keymap.of([
23883
- { key: 'Ctrl-Enter', run: onSubmit, preventDefault: true, shift: onShiftSubmit },
23884
- ...defaultKeymap
23885
- ]),
23886
- basicSetup,
23887
- sql(),
23900
+ lineNumbers(),
23901
+ highlightActiveLineGutter(),
23902
+ highlightSpecialChars(),
23903
+ history(),
23904
+ foldGutter(),
23905
+ drawSelection(),
23906
+ dropCursor(),
23907
+ EditorState.allowMultipleSelections.of(true),
23908
+ indentOnInput(),
23909
+ syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
23910
+ bracketMatching(),
23911
+ closeBrackets(),
23912
+ autocompletion(),
23913
+ rectangularSelection(),
23914
+ crosshairCursor(),
23915
+ highlightActiveLine(),
23916
+ highlightSelectionMatches(),
23917
+ editorKeymap,
23918
+ sql({
23919
+ dialect: MySQL,
23920
+ upperCaseKeywords: true,
23921
+ schema: editorSchema
23922
+ }),
23888
23923
  fixedHeightEditor,
23889
- placeholder('Ctrl-Enter to submit')
23924
+ placeholder('Let\'s query!')
23890
23925
  ]
23891
23926
  }),
23892
23927
  parent
@@ -23914,7 +23949,12 @@
23914
23949
  anchor = Math.min(parseInt(selection), window.editorView.state.doc.length);
23915
23950
  head = anchor;
23916
23951
  }
23917
- window.editorView.dispatch({ selection: { anchor, head } });
23952
+ window.editorView.dispatch({
23953
+ selection: {
23954
+ anchor,
23955
+ head
23956
+ }
23957
+ });
23918
23958
  }
23919
23959
 
23920
23960
  function focus () {
@@ -24341,7 +24381,9 @@
24341
24381
  if (window.sqlFetch === sqlFetch) {
24342
24382
  if (sqlFetch.state === 'pending' || sqlFetch.spinner === 'always') {
24343
24383
  displaySqlFetch(sqlFetch);
24344
- setTimeout(() => { updateResultTime(sqlFetch); }, 500);
24384
+ setTimeout(() => {
24385
+ updateResultTime(sqlFetch);
24386
+ }, 500);
24345
24387
  }
24346
24388
  }
24347
24389
  }
@@ -24592,12 +24634,15 @@
24592
24634
 
24593
24635
  function displaySqlFetchError (statusElementId, message, details) {
24594
24636
  const statusElement = document.getElementById(statusElementId);
24637
+ let statusMessage = 'error: ' + message;
24638
+ if (statusMessage.length > 90) {
24639
+ statusMessage = statusMessage.substring(0, 90) + '…';
24640
+ }
24595
24641
  if (details) {
24596
24642
  console.log(`${message}\n${details}`);
24597
- statusElement.innerText = `error: ${message} (check console)`;
24598
- } else {
24599
- statusElement.innerText = `error: ${message}`;
24643
+ statusMessage += ' (check console)';
24600
24644
  }
24645
+ statusElement.innerText = statusMessage;
24601
24646
  }
24602
24647
 
24603
24648
  function clearSpinner () {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqlui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.31
4
+ version: 0.1.32
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Dower
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-07 00:00:00.000000000 Z
11
+ date: 2022-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mysql2