sqlui 0.1.31 → 0.1.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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