[mod] wsl
This commit is contained in:
parent
b741dc5952
commit
ddd772f563
69 changed files with 26660 additions and 25940 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
#Ignoring git and other folders
|
#Ignoring git and other folders
|
||||||
.git
|
.git
|
||||||
.github
|
.github
|
||||||
.settings
|
.settings
|
||||||
src/
|
src/
|
||||||
#Ignoring all the markdown
|
#Ignoring all the markdown
|
||||||
*.md
|
*.md
|
||||||
26
.vscode/launch.json
vendored
26
.vscode/launch.json
vendored
|
|
@ -1,14 +1,14 @@
|
||||||
{
|
{
|
||||||
// Use IntelliSense to learn about possible attributes.
|
// Use IntelliSense to learn about possible attributes.
|
||||||
// Hover to view descriptions of existing attributes.
|
// Hover to view descriptions of existing attributes.
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
|
|
||||||
{
|
{
|
||||||
"type": "jdk",
|
"type": "jdk",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Launch Java App"
|
"name": "Launch Java App"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
146
LICENSE
146
LICENSE
|
|
@ -1,73 +1,73 @@
|
||||||
Apache License
|
Apache License
|
||||||
Version 2.0, January 2004
|
Version 2.0, January 2004
|
||||||
http://www.apache.org/licenses/
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
1. Definitions.
|
1. Definitions.
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
|
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
|
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
|
||||||
|
|
||||||
Copyright 2025 Andy Bunce
|
Copyright 2025 Andy Bunce
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
|
||||||
176
README.md
176
README.md
|
|
@ -1,88 +1,88 @@
|
||||||
Work in progress.
|
Work in progress.
|
||||||
|
|
||||||
An attempt to write a [Language Server Protocol](https://en.wikipedia.org/wiki/Language_Server_Protocol) server for and in XQuery 4.0. It tracks the draft specifications at https://qt4cg.org/
|
An attempt to write a [Language Server Protocol](https://en.wikipedia.org/wiki/Language_Server_Protocol) server for and in XQuery 4.0. It tracks the draft specifications at https://qt4cg.org/
|
||||||
It written for BaseX 12.0 and uses the [BaseX websocket](https://docs.basex.org/main/WebSockets) feature.
|
It written for BaseX 12.0 and uses the [BaseX websocket](https://docs.basex.org/main/WebSockets) feature.
|
||||||
|
|
||||||
# Demo
|
# Demo
|
||||||
The demos expect `Docker` or `Podman` on the local machine. This is only a requirement for the demos.
|
The demos expect `Docker` or `Podman` on the local machine. This is only a requirement for the demos.
|
||||||
|
|
||||||
1 Clone this repo
|
1 Clone this repo
|
||||||
2. Run `docker compose up -d` The LSP server shall now running on port 3000 (edit `compose.yaml` to change port)
|
2. Run `docker compose up -d` The LSP server shall now running on port 3000 (edit `compose.yaml` to change port)
|
||||||
3. In a browser navigate to `http://localhost:3000/static/clients/codemirror/` to see the CodeMirror 6 demo.
|
3. In a browser navigate to `http://localhost:3000/static/clients/codemirror/` to see the CodeMirror 6 demo.
|
||||||
|
|
||||||
In principle, the LSP can be used in any environment that can make use of a LSP server accessed via a websocket.
|
In principle, the LSP can be used in any environment that can make use of a LSP server accessed via a websocket.
|
||||||
## LSP Server
|
## LSP Server
|
||||||
* `webapp/lsp` The LSP implementation in XQuery using WebSockets for transport and the [JSON-RPC](https://www.jsonrpc.org/specification) 2.0 API for data format.
|
* `webapp/lsp` The LSP implementation in XQuery using WebSockets for transport and the [JSON-RPC](https://www.jsonrpc.org/specification) 2.0 API for data format.
|
||||||
|
|
||||||
## Sample html clients
|
## Sample html clients
|
||||||
|
|
||||||
Samples using common browser based code editors are available. The `CodeMirror 6` sample is the most functional.
|
Samples using common browser based code editors are available. The `CodeMirror 6` sample is the most functional.
|
||||||
|
|
||||||
These examples are self contained (no internet access required). Some make use of recent html features, for instance [popovertarget](https://caniuse.com/?search=popovertarget)
|
These examples are self contained (no internet access required). Some make use of recent html features, for instance [popovertarget](https://caniuse.com/?search=popovertarget)
|
||||||
### `CodeMirror6` https://codemirror.net/
|
### `CodeMirror6` https://codemirror.net/
|
||||||
* `webapp/static/codemirror` A test html page using the [CodeMirror6 editor](https://codemirror.net/) that connects to the BaseX LSP instance
|
* `webapp/static/codemirror` A test html page using the [CodeMirror6 editor](https://codemirror.net/) that connects to the BaseX LSP instance
|
||||||
|
|
||||||
#### uses
|
#### uses
|
||||||
* https://codemirror.net/docs/ref/#lsp-client
|
* https://codemirror.net/docs/ref/#lsp-client
|
||||||
* [https://github.com/codemirror/legacy-modes/](https://github.com/codemirror/legacy-modes/blob/main/README.md#modexquery) `xquery` mode provides browser based syntax highlighting (XQuery 3.1?)
|
* [https://github.com/codemirror/legacy-modes/](https://github.com/codemirror/legacy-modes/blob/main/README.md#modexquery) `xquery` mode provides browser based syntax highlighting (XQuery 3.1?)
|
||||||
#### alternative LSP interfaces
|
#### alternative LSP interfaces
|
||||||
* https://github.com/FurqanSoftware/codemirror-languageserver
|
* https://github.com/FurqanSoftware/codemirror-languageserver
|
||||||
* https://hjr265.me/blog/codemirror-lsp/
|
* https://hjr265.me/blog/codemirror-lsp/
|
||||||
|
|
||||||
### `Ace Editor`
|
### `Ace Editor`
|
||||||
* `webapp/static/ace` A test html page using the [Ace editor](https://ace.c9.io/) that connects to the BaseX LSP instance
|
* `webapp/static/ace` A test html page using the [Ace editor](https://ace.c9.io/) that connects to the BaseX LSP instance
|
||||||
@TODO fix
|
@TODO fix
|
||||||
#### Uses
|
#### Uses
|
||||||
* https://github.com/mkslanc/ace-linters https://mkslanc.github.io/ace-linters/
|
* https://github.com/mkslanc/ace-linters https://mkslanc.github.io/ace-linters/
|
||||||
|
|
||||||
Make a websocket server for lsp on port 3000
|
Make a websocket server for lsp on port 3000
|
||||||
https://mkslanc.github.io/ace-linters/websocket.html
|
https://mkslanc.github.io/ace-linters/websocket.html
|
||||||
|
|
||||||
http://localhost:3000/exampleServer
|
http://localhost:3000/exampleServer
|
||||||
|
|
||||||
https://github.com/mkslanc/ace-linters/blob/c1b317e01299016ac7da6588361228637f4eac25/packages/demo/websockets-lsp/server/server.ts
|
https://github.com/mkslanc/ace-linters/blob/c1b317e01299016ac7da6588361228637f4eac25/packages/demo/websockets-lsp/server/server.ts
|
||||||
I needed `set NODE_OPTIONS=--max_old_space_size=8192` for build to complete
|
I needed `set NODE_OPTIONS=--max_old_space_size=8192` for build to complete
|
||||||
|
|
||||||
Or `node --max-old-space-size=8192 node_modules/webpack-dev-serve
|
Or `node --max-old-space-size=8192 node_modules/webpack-dev-serve
|
||||||
r/bin/webpack-dev-server.js`
|
r/bin/webpack-dev-server.js`
|
||||||
|
|
||||||
### `Monaco editor`
|
### `Monaco editor`
|
||||||
@TODO create
|
@TODO create
|
||||||
https://socket.dev/npm/package/monaco-editor
|
https://socket.dev/npm/package/monaco-editor
|
||||||
|
|
||||||
### Server dev notes
|
### Server dev notes
|
||||||
|
|
||||||
State is held in [websocket attributes](https://docs.basex.org/main/WebSocket_Functions#websocket_attributes).
|
State is held in [websocket attributes](https://docs.basex.org/main/WebSocket_Functions#websocket_attributes).
|
||||||
|
|
||||||
|Name|Use|
|
|Name|Use|
|
||||||
|----|---|
|
|----|---|
|
||||||
|id|wsid|
|
|id|wsid|
|
||||||
|connectTime|dateTime of connection|
|
|connectTime|dateTime of connection|
|
||||||
|initialized|set true after client sends initialized message|
|
|initialized|set true after client sends initialized message|
|
||||||
|client|the client initialize message|
|
|client|the client initialize message|
|
||||||
|files|A map whose keys are open uris, values are maps (doctype-> attribute name where doctype is stored| |
|
|files|A map whose keys are open uris, values are maps (doctype-> attribute name where doctype is stored| |
|
||||||
|file-{uuid}|name of websocket attribute containing the textDocument|
|
|file-{uuid}|name of websocket attribute containing the textDocument|
|
||||||
|parse-{uuid}|name of websocket attribute containing parse tree XML|
|
|parse-{uuid}|name of websocket attribute containing parse tree XML|
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
WS->>lsp-ws: message
|
WS->>lsp-ws: message
|
||||||
lsp-ws->>rpc: reply
|
lsp-ws->>rpc: reply
|
||||||
rpc->>+John: John, can you hear me?
|
rpc->>+John: John, can you hear me?
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### XQuery 4.0 parser
|
#### XQuery 4.0 parser
|
||||||
The ebnf is taken from Gunther Rademacher's rex-parser-generator
|
The ebnf is taken from Gunther Rademacher's rex-parser-generator
|
||||||
[XQuery-40.ebnf](https://github.com/GuntherRademacher/rex-parser-generator/blob/main/docs/sample-grammars/XQuery-40.ebnf)
|
[XQuery-40.ebnf](https://github.com/GuntherRademacher/rex-parser-generator/blob/main/docs/sample-grammars/XQuery-40.ebnf)
|
||||||
|
|
||||||
The script [scripts/rex.xq](scripts/rex.xq) can generate XQuery or Java parser code from this.
|
The script [scripts/rex.xq](scripts/rex.xq) can generate XQuery or Java parser code from this.
|
||||||
The npm `package.json` script `javac` can create a jar file from the Java source.
|
The npm `package.json` script `javac` can create a jar file from the Java source.
|
||||||
## Related links
|
## Related links
|
||||||
java -cp org.eclipse.lemminx-uber.jar org.eclipse.lemminx.XMLServerSocketLauncher`
|
java -cp org.eclipse.lemminx-uber.jar org.eclipse.lemminx.XMLServerSocketLauncher`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,137 +1,137 @@
|
||||||
|
|
||||||
import { EditorState, StateEffect, Compartment } from '@codemirror/state';
|
import { EditorState, StateEffect, Compartment } from '@codemirror/state';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
lineNumbers, highlightActiveLineGutter, highlightWhitespace,
|
lineNumbers, highlightActiveLineGutter, highlightWhitespace,
|
||||||
drawSelection, rectangularSelection, crosshairCursor, highlightActiveLine,
|
drawSelection, rectangularSelection, crosshairCursor, highlightActiveLine,
|
||||||
keymap, dropCursor, EditorView,tooltips
|
keymap, dropCursor, EditorView,tooltips
|
||||||
} from '@codemirror/view';
|
} from '@codemirror/view';
|
||||||
|
|
||||||
import { openSearchPanel, highlightSelectionMatches, searchKeymap } from '@codemirror/search';
|
import { openSearchPanel, highlightSelectionMatches, searchKeymap } from '@codemirror/search';
|
||||||
|
|
||||||
import { openLintPanel, lintGutter, lintKeymap, linter } from "@codemirror/lint"
|
import { openLintPanel, lintGutter, lintKeymap, linter } from "@codemirror/lint"
|
||||||
|
|
||||||
import { indentWithTab, history, defaultKeymap, historyKeymap } from '@codemirror/commands';
|
import { indentWithTab, history, defaultKeymap, historyKeymap } from '@codemirror/commands';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
foldGutter, indentOnInput, indentUnit, bracketMatching, foldKeymap,
|
foldGutter, indentOnInput, indentUnit, bracketMatching, foldKeymap,
|
||||||
syntaxHighlighting, defaultHighlightStyle, StreamLanguage
|
syntaxHighlighting, defaultHighlightStyle, StreamLanguage
|
||||||
} from '@codemirror/language';
|
} from '@codemirror/language';
|
||||||
|
|
||||||
import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete';
|
import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
LSPClient, LSPPlugin, languageServerSupport, languageServerExtensions,
|
LSPClient, LSPPlugin, languageServerSupport, languageServerExtensions,
|
||||||
formatDocument, formatKeymap
|
formatDocument, formatKeymap
|
||||||
} from "@codemirror/lsp-client";
|
} from "@codemirror/lsp-client";
|
||||||
|
|
||||||
import { xQuery } from "@codemirror/legacy-modes/mode/xquery"
|
import { xQuery } from "@codemirror/legacy-modes/mode/xquery"
|
||||||
// Language
|
// Language
|
||||||
import { xml } from "@codemirror/lang-xml";
|
import { xml } from "@codemirror/lang-xml";
|
||||||
|
|
||||||
import { showMinimap } from "@replit/codemirror-minimap"
|
import { showMinimap } from "@replit/codemirror-minimap"
|
||||||
let create = (v) => {
|
let create = (v) => {
|
||||||
const dom = document.createElement('div');
|
const dom = document.createElement('div');
|
||||||
return { dom }
|
return { dom }
|
||||||
}
|
}
|
||||||
const compartment = new Compartment();
|
const compartment = new Compartment();
|
||||||
let curOpts = {
|
let curOpts = {
|
||||||
lineWrap: true,
|
lineWrap: true,
|
||||||
minimap: true,
|
minimap: true,
|
||||||
highlightWhitespace: true
|
highlightWhitespace: true
|
||||||
}
|
}
|
||||||
// array of extensions reflecting opts
|
// array of extensions reflecting opts
|
||||||
function optExts(opts) {
|
function optExts(opts) {
|
||||||
let exts = []
|
let exts = []
|
||||||
if (opts.lineWrap) exts.push(EditorView.lineWrapping)
|
if (opts.lineWrap) exts.push(EditorView.lineWrapping)
|
||||||
if (opts.highlightWhitespace) exts.push(highlightWhitespace())
|
if (opts.highlightWhitespace) exts.push(highlightWhitespace())
|
||||||
if (opts.minimap) exts.push(
|
if (opts.minimap) exts.push(
|
||||||
showMinimap.compute(['doc'], (state) => {
|
showMinimap.compute(['doc'], (state) => {
|
||||||
return {
|
return {
|
||||||
create,
|
create,
|
||||||
/* optional showOverlay: 'mouse-over' */
|
/* optional showOverlay: 'mouse-over' */
|
||||||
displayText: 'characters'
|
displayText: 'characters'
|
||||||
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
return exts
|
return exts
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCompartment(opts) {
|
function updateCompartment(opts) {
|
||||||
view.dispatch({
|
view.dispatch({
|
||||||
effects: [compartment.reconfigure(optExts(opts))]
|
effects: [compartment.reconfigure(optExts(opts))]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// return promise with socket map or reject if no connect
|
// return promise with socket map or reject if no connect
|
||||||
function simpleWebSocketTransport(uri) {
|
function simpleWebSocketTransport(uri) {
|
||||||
let handlers = [];
|
let handlers = [];
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
let sock = new WebSocket(uri);
|
let sock = new WebSocket(uri);
|
||||||
|
|
||||||
sock.onmessage = e => { for (let h of handlers) h(e.data.toString()); };
|
sock.onmessage = e => { for (let h of handlers) h(e.data.toString()); };
|
||||||
sock.onerror = e => reject(e);
|
sock.onerror = e => reject(e);
|
||||||
sock.onopen = () => resolve({
|
sock.onopen = () => resolve({
|
||||||
socket: sock,
|
socket: sock,
|
||||||
send: (message) => sock.send(message),
|
send: (message) => sock.send(message),
|
||||||
subscribe: (handler) => handlers.push(handler),
|
subscribe: (handler) => handlers.push(handler),
|
||||||
unsubscribe: (handler) => handlers = handlers.filter(h => h != handler)
|
unsubscribe: (handler) => handlers = handlers.filter(h => h != handler)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseExts = [
|
const baseExts = [
|
||||||
lineNumbers(),
|
lineNumbers(),
|
||||||
highlightActiveLineGutter(),
|
highlightActiveLineGutter(),
|
||||||
history(),
|
history(),
|
||||||
foldGutter(),
|
foldGutter(),
|
||||||
lintGutter(),
|
lintGutter(),
|
||||||
drawSelection(),
|
drawSelection(),
|
||||||
dropCursor(),
|
dropCursor(),
|
||||||
EditorState.allowMultipleSelections.of(true),
|
EditorState.allowMultipleSelections.of(true),
|
||||||
tooltips({ }), // clipped
|
tooltips({ }), // clipped
|
||||||
keymap.of([indentWithTab]),
|
keymap.of([indentWithTab]),
|
||||||
indentOnInput(),
|
indentOnInput(),
|
||||||
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
||||||
bracketMatching(),
|
bracketMatching(),
|
||||||
closeBrackets(),
|
closeBrackets(),
|
||||||
autocompletion(),
|
autocompletion(),
|
||||||
rectangularSelection(),
|
rectangularSelection(),
|
||||||
crosshairCursor(),
|
crosshairCursor(),
|
||||||
highlightActiveLine(),
|
highlightActiveLine(),
|
||||||
highlightSelectionMatches(),
|
highlightSelectionMatches(),
|
||||||
keymap.of([
|
keymap.of([
|
||||||
...closeBracketsKeymap,
|
...closeBracketsKeymap,
|
||||||
...defaultKeymap,
|
...defaultKeymap,
|
||||||
...searchKeymap,
|
...searchKeymap,
|
||||||
...historyKeymap,
|
...historyKeymap,
|
||||||
...foldKeymap,
|
...foldKeymap,
|
||||||
...completionKeymap,
|
...completionKeymap,
|
||||||
...lintKeymap
|
...lintKeymap
|
||||||
]),
|
]),
|
||||||
StreamLanguage.define(xQuery),
|
StreamLanguage.define(xQuery),
|
||||||
compartment.of(optExts(curOpts))
|
compartment.of(optExts(curOpts))
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// map cmd->{keybings,fn}
|
// map cmd->{keybings,fn}
|
||||||
function listCommands(view) {
|
function listCommands(view) {
|
||||||
const commands = new Map();
|
const commands = new Map();
|
||||||
const keymaps = view.state.facet(keymap);
|
const keymaps = view.state.facet(keymap);
|
||||||
for (let km of keymaps) {
|
for (let km of keymaps) {
|
||||||
for (let binding of km) {
|
for (let binding of km) {
|
||||||
if (binding.run && binding.run.name) {
|
if (binding.run && binding.run.name) {
|
||||||
commands.set(binding.run.name, { key: binding.key, fn: binding.run });
|
commands.set(binding.run.name, { key: binding.key, fn: binding.run });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return commands;
|
return commands;
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
baseExts, EditorView, EditorState, StateEffect, LSPPlugin, LSPClient,
|
baseExts, EditorView, EditorState, StateEffect, LSPPlugin, LSPClient,
|
||||||
openSearchPanel, openLintPanel, languageServerSupport, languageServerExtensions,
|
openSearchPanel, openLintPanel, languageServerSupport, languageServerExtensions,
|
||||||
simpleWebSocketTransport, linter, formatDocument, keymap, formatKeymap, listCommands, updateCompartment, curOpts
|
simpleWebSocketTransport, linter, formatDocument, keymap, formatKeymap, listCommands, updateCompartment, curOpts
|
||||||
};
|
};
|
||||||
|
|
@ -1,41 +1,41 @@
|
||||||
import {basicSetup, EditorView} from "codemirror"
|
import {basicSetup, EditorView} from "codemirror"
|
||||||
import { EditorState } from '@codemirror/state';
|
import { EditorState } from '@codemirror/state';
|
||||||
import { LSPClient, LSPPlugin, languageServerSupport } from "@codemirror/lsp-client";
|
import { LSPClient, LSPPlugin, languageServerSupport } from "@codemirror/lsp-client";
|
||||||
import {StreamLanguage} from "@codemirror/language"
|
import {StreamLanguage} from "@codemirror/language"
|
||||||
import { xQuery } from "@codemirror/legacy-modes/mode/xquery"
|
import { xQuery } from "@codemirror/legacy-modes/mode/xquery"
|
||||||
|
|
||||||
function simpleWebSocketTransport(uri) {
|
function simpleWebSocketTransport(uri) {
|
||||||
let handlers = [];
|
let handlers = [];
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
let sock = new WebSocket(uri);
|
let sock = new WebSocket(uri);
|
||||||
|
|
||||||
sock.onmessage = e => { for (let h of handlers) h(e.data.toString()); };
|
sock.onmessage = e => { for (let h of handlers) h(e.data.toString()); };
|
||||||
sock.onerror = e => reject(e);
|
sock.onerror = e => reject(e);
|
||||||
sock.onopen = () => resolve({
|
sock.onopen = () => resolve({
|
||||||
socket: sock,
|
socket: sock,
|
||||||
send: (message) => sock.send(message),
|
send: (message) => sock.send(message),
|
||||||
subscribe: (handler) => handlers.push(handler),
|
subscribe: (handler) => handlers.push(handler),
|
||||||
unsubscribe: (handler) => handlers = handlers.filter(h => h != handler)
|
unsubscribe: (handler) => handlers = handlers.filter(h => h != handler)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
simpleWebSocketTransport("ws://localhost:3000/ws/lsp")
|
simpleWebSocketTransport("ws://localhost:3000/ws/lsp")
|
||||||
.then(transport => {
|
.then(transport => {
|
||||||
|
|
||||||
client = new LSPClient().connect(transport);
|
client = new LSPClient().connect(transport);
|
||||||
|
|
||||||
let extLsp = languageServerSupport(client, file, "xquery");
|
let extLsp = languageServerSupport(client, file, "xquery");
|
||||||
|
|
||||||
const doc = view.state.doc.toString();
|
const doc = view.state.doc.toString();
|
||||||
const state = lsp.createEditorState(doc, [...lsp.baseExts, extLsp, extLint]);
|
const state = lsp.createEditorState(doc, [...lsp.baseExts, extLsp, extLint]);
|
||||||
view.setState(state);
|
view.setState(state);
|
||||||
})
|
})
|
||||||
.catch(r => { alert("connection failed: " + server) });
|
.catch(r => { alert("connection failed: " + server) });
|
||||||
|
|
||||||
|
|
||||||
new EditorView({
|
new EditorView({
|
||||||
doc: "xquery version '3.1';\n(:~ comment:)\nmodule namespace pdfbox='ns';\n",
|
doc: "xquery version '3.1';\n(:~ comment:)\nmodule namespace pdfbox='ns';\n",
|
||||||
extensions: [basicSetup, StreamLanguage.define(xQuery)],
|
extensions: [basicSetup, StreamLanguage.define(xQuery)],
|
||||||
parent: document.body
|
parent: document.body
|
||||||
});
|
});
|
||||||
|
|
@ -1,28 +1,28 @@
|
||||||
import * as aceBuilds from 'https://esm.run/ace-builds';
|
import * as aceBuilds from 'https://esm.run/ace-builds';
|
||||||
|
|
||||||
import ace from 'https://cdn.jsdelivr.net/npm/ace/+esm'
|
import ace from 'https://cdn.jsdelivr.net/npm/ace/+esm'
|
||||||
|
|
||||||
/* import 'ace-builds/src-noconflict/mode-javascript';
|
/* import 'ace-builds/src-noconflict/mode-javascript';
|
||||||
import 'ace-builds/src-noconflict/theme-chrome'; */
|
import 'ace-builds/src-noconflict/theme-chrome'; */
|
||||||
|
|
||||||
/* import {AceLanguageClient} from "ace-linters/build/ace-language-client";
|
/* import {AceLanguageClient} from "ace-linters/build/ace-language-client";
|
||||||
|
|
||||||
const serverData = {
|
const serverData = {
|
||||||
module: () => import("ace-linters/build/language-client"),
|
module: () => import("ace-linters/build/language-client"),
|
||||||
modes: "json|json5",
|
modes: "json|json5",
|
||||||
type: "socket",
|
type: "socket",
|
||||||
socket: new WebSocket("ws://127.0.0.1:3000/ws/lsp"), // your websocket server address
|
socket: new WebSocket("ws://127.0.0.1:3000/ws/lsp"), // your websocket server address
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// Initialize the editor
|
// Initialize the editor
|
||||||
const editor = ace.edit("editor", {
|
const editor = ace.edit("editor", {
|
||||||
theme: "ace/theme/chrome",
|
theme: "ace/theme/chrome",
|
||||||
mode: "ace/mode/javascript",
|
mode: "ace/mode/javascript",
|
||||||
fontSize: "14px",
|
fontSize: "14px",
|
||||||
showPrintMargin: false,
|
showPrintMargin: false,
|
||||||
useWorker: false // Disable web worker for this simple demo
|
useWorker: false // Disable web worker for this simple demo
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a language provider for WebSocket
|
// Create a language provider for WebSocket
|
||||||
//let languageProvider = AceLanguageClient.for(serverData);
|
//let languageProvider = AceLanguageClient.for(serverData);
|
||||||
//languageProvider.registerEditor(editor);
|
//languageProvider.registerEditor(editor);
|
||||||
|
|
@ -1,44 +1,44 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en-US">
|
<html lang="en-US">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>BaseX LSP</title>
|
<title>BaseX LSP</title>
|
||||||
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ace.js"></script>
|
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ace.js"></script>
|
||||||
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ext-language_tools.js"></script>
|
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ext-language_tools.js"></script>
|
||||||
<script src="https://www.unpkg.com/ace-linters@latest/build/ace-linters.js"></script>
|
<script src="https://www.unpkg.com/ace-linters@latest/build/ace-linters.js"></script>
|
||||||
<script src="https://www.unpkg.com/ace-linters@latest/build/ace-language-client.js"></script>
|
<script src="https://www.unpkg.com/ace-linters@latest/build/ace-language-client.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div>something</div>
|
<div>something</div>
|
||||||
<div id="editor" style="height: 100px">some text</div>
|
<div id="editor" style="height: 100px">some text</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let servers = [
|
let servers = [
|
||||||
{
|
{
|
||||||
module: () => import("ace-linters/build/language-client"),
|
module: () => import("ace-linters/build/language-client"),
|
||||||
modes: "astro",
|
modes: "astro",
|
||||||
type: "socket",
|
type: "socket",
|
||||||
socket: new WebSocket("ws://127.0.0.1:8080/ws/lsp"
|
socket: new WebSocket("ws://127.0.0.1:8080/ws/lsp"
|
||||||
//"ws://127.0.0.1:3000/exampleserver"
|
//"ws://127.0.0.1:3000/exampleserver"
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
let languageProvider = AceLanguageClient.for(servers);
|
let languageProvider = AceLanguageClient.for(servers);
|
||||||
|
|
||||||
ace.require("ace/ext/language_tools"); //To allow autocompletion
|
ace.require("ace/ext/language_tools"); //To allow autocompletion
|
||||||
var editor = ace.edit("editor", {
|
var editor = ace.edit("editor", {
|
||||||
enableBasicAutocompletion: true,
|
enableBasicAutocompletion: true,
|
||||||
enableLiveAutocompletion: true,
|
enableLiveAutocompletion: true,
|
||||||
mode: "ace/mode/json"
|
mode: "ace/mode/json"
|
||||||
});
|
});
|
||||||
|
|
||||||
languageProvider.registerEditor(editor);
|
languageProvider.registerEditor(editor);
|
||||||
editor.session.setMode("astro"); // mode now contains "ace/mode/javascript".
|
editor.session.setMode("astro"); // mode now contains "ace/mode/javascript".
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,39 +1,39 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
<title>Editor</title>
|
<title>Editor</title>
|
||||||
<style type="text/css" media="screen">
|
<style type="text/css" media="screen">
|
||||||
body {
|
body {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
#editor {
|
#editor {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<pre id="editor">function foo(items) {
|
<pre id="editor">function foo(items) {
|
||||||
var i;
|
var i;
|
||||||
for (i = 0; i < items.length; i++) {
|
for (i = 0; i < items.length; i++) {
|
||||||
alert("Ace Rocks " + items[i]);
|
alert("Ace Rocks " + items[i]);
|
||||||
}
|
}
|
||||||
}</pre>
|
}</pre>
|
||||||
|
|
||||||
<script src="src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
|
<script src="src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script>
|
<script>
|
||||||
var editor = ace.edit("editor");
|
var editor = ace.edit("editor");
|
||||||
editor.setTheme("ace/theme/twilight");
|
editor.setTheme("ace/theme/twilight");
|
||||||
editor.session.setMode("ace/mode/javascript");
|
editor.session.setMode("ace/mode/javascript");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
REM default port 5008
|
REM default port 5008
|
||||||
REM https://download.eclipse.org/lemminx/releases/0.31.0/
|
REM https://download.eclipse.org/lemminx/releases/0.31.0/
|
||||||
java -cp org.eclipse.lemminx-uber.jar org.eclipse.lemminx.XMLServerSocketLauncher
|
java -cp org.eclipse.lemminx-uber.jar org.eclipse.lemminx.XMLServerSocketLauncher
|
||||||
|
|
@ -1,72 +1,72 @@
|
||||||
(:~ web socket for ace
|
(:~ web socket for ace
|
||||||
:)
|
:)
|
||||||
module namespace lsp="urn:quodatum:vscode";
|
module namespace lsp="urn:quodatum:vscode";
|
||||||
import module namespace ws = "http://basex.org/modules/ws";
|
import module namespace ws = "http://basex.org/modules/ws";
|
||||||
|
|
||||||
declare
|
declare
|
||||||
%ws:connect('/ws/exampleServer')
|
%ws:connect('/ws/exampleServer')
|
||||||
function lsp:connect()
|
function lsp:connect()
|
||||||
as empty-sequence(){
|
as empty-sequence(){
|
||||||
let $_:=trace(ws:id(),"BaseX socket id: ")
|
let $_:=trace(ws:id(),"BaseX socket id: ")
|
||||||
return ()
|
return ()
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~
|
(:~
|
||||||
: Processes a WebSocket message.
|
: Processes a WebSocket message.
|
||||||
: @param $message message
|
: @param $message message
|
||||||
:)
|
:)
|
||||||
declare
|
declare
|
||||||
%ws:message('/ws/exampleServer', '{$message}')
|
%ws:message('/ws/exampleServer', '{$message}')
|
||||||
function lsp:message(
|
function lsp:message(
|
||||||
$message as xs:string
|
$message as xs:string
|
||||||
) as empty-sequence() {
|
) as empty-sequence() {
|
||||||
let $json:=json:parse($message, map{ 'format': 'xquery' })
|
let $json:=json:parse($message, map{ 'format': 'xquery' })
|
||||||
let $id:=$json?id
|
let $id:=$json?id
|
||||||
let $_:=trace($id,"MESSAGE id: ")
|
let $_:=trace($id,"MESSAGE id: ")
|
||||||
return switch($json?method=>trace("method: "))
|
return switch($json?method=>trace("method: "))
|
||||||
case "initialize" return
|
case "initialize" return
|
||||||
let $a:=map{
|
let $a:=map{
|
||||||
"capabilities":map{"textDocumentSync":2,
|
"capabilities":map{"textDocumentSync":2,
|
||||||
"completionProvider":map{"resolveProvider":false(),"triggerCharacters":["\",":"]},
|
"completionProvider":map{"resolveProvider":false(),"triggerCharacters":["\",":"]},
|
||||||
"hoverProvider":true(),
|
"hoverProvider":true(),
|
||||||
"documentSymbolProvider":true(),
|
"documentSymbolProvider":true(),
|
||||||
"documentRangeFormattingProvider":false(),
|
"documentRangeFormattingProvider":false(),
|
||||||
"colorProvider":map{},
|
"colorProvider":map{},
|
||||||
"foldingRangeProvider":true(),
|
"foldingRangeProvider":true(),
|
||||||
"selectionRangeProvider":true(),
|
"selectionRangeProvider":true(),
|
||||||
"documentLinkProvider":map{}
|
"documentLinkProvider":map{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let $a:=trace($a,"A: ")
|
let $a:=trace($a,"A: ")
|
||||||
return lsp:send-result($a,$id,ws:id())
|
return lsp:send-result($a,$id,ws:id())
|
||||||
default
|
default
|
||||||
return error()
|
return error()
|
||||||
};
|
};
|
||||||
|
|
||||||
declare %ws:error('/ws/exampleServer', '{$error}')
|
declare %ws:error('/ws/exampleServer', '{$error}')
|
||||||
function lsp:error($error)
|
function lsp:error($error)
|
||||||
{
|
{
|
||||||
let $_:=trace($error,"ERROR ")
|
let $_:=trace($error,"ERROR ")
|
||||||
return ()
|
return ()
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~
|
(:~
|
||||||
: Closes a WebSocket connection. Unregisters the user and notifies all clients.
|
: Closes a WebSocket connection. Unregisters the user and notifies all clients.
|
||||||
:)
|
:)
|
||||||
declare
|
declare
|
||||||
%ws:close('/ws/exampleServer')
|
%ws:close('/ws/exampleServer')
|
||||||
function lsp:close() as empty-sequence() {
|
function lsp:close() as empty-sequence() {
|
||||||
let $_:=trace("CLOSE")
|
let $_:=trace("CLOSE")
|
||||||
return ()
|
return ()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
declare
|
declare
|
||||||
function lsp:send-result($result as map(*),$rpcId as xs:string, $wsId as xs:string)
|
function lsp:send-result($result as map(*),$rpcId as xs:string, $wsId as xs:string)
|
||||||
as empty-sequence()
|
as empty-sequence()
|
||||||
{
|
{
|
||||||
let $json:=map{"jsonrpc":"2.0","id":$rpcId,"result":$result}=>trace("RESULT: ")
|
let $json:=map{"jsonrpc":"2.0","id":$rpcId,"result":$result}=>trace("RESULT: ")
|
||||||
return ws:send($json,$wsId)
|
return ws:send($json,$wsId)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<script>
|
<script>
|
||||||
const webSocket = new WebSocket("ws://localhost:5008");
|
const webSocket = new WebSocket("ws://localhost:5008");
|
||||||
alert("hi");
|
alert("hi");
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -1,30 +1,30 @@
|
||||||
import "ace-code/esm-resolver";
|
import "ace-code/esm-resolver";
|
||||||
import {jsonContent} from "../docs-example/json-example";
|
import {jsonContent} from "../docs-example/json-example";
|
||||||
|
|
||||||
import {json5Content, json5Schema} from "../docs-example/json5-example";
|
import {json5Content, json5Schema} from "../docs-example/json5-example";
|
||||||
|
|
||||||
import {addFormatCommand, createEditorWithLSP} from "../utils";
|
import {addFormatCommand, createEditorWithLSP} from "../utils";
|
||||||
import {AceLanguageClient, LanguageClientConfig} from "ace-linters/build/ace-language-client";
|
import {AceLanguageClient, LanguageClientConfig} from "ace-linters/build/ace-language-client";
|
||||||
|
|
||||||
|
|
||||||
let modes = [
|
let modes = [
|
||||||
{name: "json", mode: "ace/mode/json", content: jsonContent, options: {jsonSchemaUri: "common-form.schema.json"}},
|
{name: "json", mode: "ace/mode/json", content: jsonContent, options: {jsonSchemaUri: "common-form.schema.json"}},
|
||||||
{name: "json5", mode: "ace/mode/json5", content: json5Content, options: {jsonSchemaUri: json5Schema}},
|
{name: "json5", mode: "ace/mode/json5", content: json5Content, options: {jsonSchemaUri: json5Schema}},
|
||||||
]
|
]
|
||||||
|
|
||||||
const serverData: LanguageClientConfig = {
|
const serverData: LanguageClientConfig = {
|
||||||
module: () => import("ace-linters/build/language-client"),
|
module: () => import("ace-linters/build/language-client"),
|
||||||
modes: "json|json5",
|
modes: "json|json5",
|
||||||
type: "socket",
|
type: "socket",
|
||||||
socket: new WebSocket("ws://127.0.0.1:3000/exampleServer"),
|
socket: new WebSocket("ws://127.0.0.1:3000/exampleServer"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let languageProvider = AceLanguageClient.for(serverData);
|
let languageProvider = AceLanguageClient.for(serverData);
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for (let mode of modes) {
|
for (let mode of modes) {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
createEditorWithLSP(mode, i, languageProvider);
|
createEditorWithLSP(mode, i, languageProvider);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
addFormatCommand(languageProvider);
|
addFormatCommand(languageProvider);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
# Sample language server
|
# Sample language server
|
||||||
|
|
||||||
This is just sample websocket server based on vscode-json-languageserver
|
This is just sample websocket server based on vscode-json-languageserver
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
To run the server, simply follow these steps:
|
To run the server, simply follow these steps:
|
||||||
|
|
||||||
1. Install dependencies by running `npm i`
|
1. Install dependencies by running `npm i`
|
||||||
2. Start the server by running `npm run start-server`
|
2. Start the server by running `npm run start-server`
|
||||||
|
|
||||||
And that's it! Your sample language server on 3000 port should now be up and running.
|
And that's it! Your sample language server on 3000 port should now be up and running.
|
||||||
|
|
|
||||||
1234
bundles/websockets-lsp/server/package-lock.json
generated
1234
bundles/websockets-lsp/server/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "sample-server",
|
"name": "sample-server",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start-server": "node --loader ts-node/esm server.ts"
|
"start-server": "node --loader ts-node/esm server.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vscode-json-languageserver": "^1.3.4",
|
"vscode-json-languageserver": "^1.3.4",
|
||||||
"ts-node": "^10.8.1"
|
"ts-node": "^10.8.1"
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,98 +1,98 @@
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import {WebSocketServer} from 'ws';
|
import {WebSocketServer} from 'ws';
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import {fileURLToPath, URL} from 'url';
|
import {fileURLToPath, URL} from 'url';
|
||||||
import * as net from 'net';
|
import * as net from 'net';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import * as rpc from 'vscode-ws-jsonrpc';
|
import * as rpc from 'vscode-ws-jsonrpc';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import * as jsonServer from 'vscode-json-languageserver/out/jsonServer.js'
|
import * as jsonServer from 'vscode-json-languageserver/out/jsonServer.js'
|
||||||
import requestLight from "request-light";
|
import requestLight from "request-light";
|
||||||
import vscodeUri from "vscode-uri";
|
import vscodeUri from "vscode-uri";
|
||||||
import {createConnection} from 'vscode-languageserver/lib/node/main.js';
|
import {createConnection} from 'vscode-languageserver/lib/node/main.js';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
export function startLanguageServer(webSocket: rpc.IWebSocket) {
|
export function startLanguageServer(webSocket: rpc.IWebSocket) {
|
||||||
const messageReader = new rpc.WebSocketMessageReader(webSocket);
|
const messageReader = new rpc.WebSocketMessageReader(webSocket);
|
||||||
const messageWriter = new rpc.WebSocketMessageWriter(webSocket);
|
const messageWriter = new rpc.WebSocketMessageWriter(webSocket);
|
||||||
const connection = createConnection(messageReader, messageWriter);
|
const connection = createConnection(messageReader, messageWriter);
|
||||||
jsonServer.startServer(connection, {
|
jsonServer.startServer(connection, {
|
||||||
file: getFileService(),
|
file: getFileService(),
|
||||||
http: getHTTPService(),
|
http: getHTTPService(),
|
||||||
configureHttpRequests: requestLight.configure
|
configureHttpRequests: requestLight.configure
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHTTPService() {
|
function getHTTPService() {
|
||||||
return {
|
return {
|
||||||
getContent(uri: any) {
|
getContent(uri: any) {
|
||||||
const headers = {'Accept-Encoding': 'gzip, deflate'};
|
const headers = {'Accept-Encoding': 'gzip, deflate'};
|
||||||
return requestLight.xhr({url: uri, followRedirects: 5, headers}).then(response => {
|
return requestLight.xhr({url: uri, followRedirects: 5, headers}).then(response => {
|
||||||
return response.responseText;
|
return response.responseText;
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
return Promise.reject(error.responseText || requestLight.getErrorStatusDescription(error.status) || error.toString());
|
return Promise.reject(error.responseText || requestLight.getErrorStatusDescription(error.status) || error.toString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFileService() {
|
function getFileService() {
|
||||||
return {
|
return {
|
||||||
getContent(location: any) {
|
getContent(location: any) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const uri = vscodeUri.URI.parse(location);
|
const uri = vscodeUri.URI.parse(location);
|
||||||
fs.readFile(uri.fsPath, 'utf8', (err, data) => {
|
fs.readFile(uri.fsPath, 'utf8', (err, data) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
} else {
|
} else {
|
||||||
resolve(data);
|
resolve(data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const serverFilePath = fileURLToPath(import.meta.url);
|
const serverFilePath = fileURLToPath(import.meta.url);
|
||||||
const serverDir = path.dirname(serverFilePath);
|
const serverDir = path.dirname(serverFilePath);
|
||||||
|
|
||||||
process.on('uncaughtException', (err: any) => {
|
process.on('uncaughtException', (err: any) => {
|
||||||
console.error('Uncaught Exception: ', err.toString());
|
console.error('Uncaught Exception: ', err.toString());
|
||||||
if (err.stack) {
|
if (err.stack) {
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(express.static(serverDir));
|
app.use(express.static(serverDir));
|
||||||
const server = app.listen(3000);
|
const server = app.listen(3000);
|
||||||
|
|
||||||
const webSocketServer = new WebSocketServer({
|
const webSocketServer = new WebSocketServer({
|
||||||
noServer: true,
|
noServer: true,
|
||||||
perMessageDeflate: false
|
perMessageDeflate: false
|
||||||
});
|
});
|
||||||
server.on('upgrade', (request: http.IncomingMessage, socket: net.Socket, head: Buffer) => {
|
server.on('upgrade', (request: http.IncomingMessage, socket: net.Socket, head: Buffer) => {
|
||||||
const baseURL = `http://${request.headers.host}/`;
|
const baseURL = `http://${request.headers.host}/`;
|
||||||
const pathname = request.url ? new URL(request.url, baseURL).pathname : undefined;
|
const pathname = request.url ? new URL(request.url, baseURL).pathname : undefined;
|
||||||
if (pathname === '/exampleServer') {
|
if (pathname === '/exampleServer') {
|
||||||
webSocketServer.handleUpgrade(request, socket, head, webSocket => {
|
webSocketServer.handleUpgrade(request, socket, head, webSocket => {
|
||||||
const socket: rpc.IWebSocket = {
|
const socket: rpc.IWebSocket = {
|
||||||
send: content => webSocket.send(content, error => {
|
send: content => webSocket.send(content, error => {
|
||||||
if (error) {
|
if (error) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
onMessage: cb => webSocket.on('message', cb),
|
onMessage: cb => webSocket.on('message', cb),
|
||||||
onError: cb => webSocket.on('error', cb),
|
onError: cb => webSocket.on('error', cb),
|
||||||
onClose: cb => webSocket.on('close', cb),
|
onClose: cb => webSocket.on('close', cb),
|
||||||
dispose: () => webSocket.close()
|
dispose: () => webSocket.close()
|
||||||
};
|
};
|
||||||
if (webSocket.readyState === webSocket.OPEN) {
|
if (webSocket.readyState === webSocket.OPEN) {
|
||||||
startLanguageServer(socket);
|
startLanguageServer(socket);
|
||||||
} else {
|
} else {
|
||||||
webSocket.on('open', () => startLanguageServer(socket));
|
webSocket.on('open', () => startLanguageServer(socket));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
46
compose.yaml
46
compose.yaml
|
|
@ -1,23 +1,23 @@
|
||||||
# basex lsp, use with
|
# basex lsp, use with
|
||||||
services:
|
services:
|
||||||
basex:
|
basex:
|
||||||
image: ghcr.io/quodatum/basexhttp:basex-12.0
|
image: ghcr.io/quodatum/basexhttp:basex-12.0
|
||||||
container_name: basex-lsp
|
container_name: basex-lsp
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "3000:8080"
|
- "3000:8080"
|
||||||
- "3001:1984"
|
- "3001:1984"
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/srv/basex/data
|
- ./data:/srv/basex/data
|
||||||
# - ./webapp/web.xml:/srv/basex/webapp/WEB-INF/web.xml # set websocket options 12.1+
|
# - ./webapp/web.xml:/srv/basex/webapp/WEB-INF/web.xml # set websocket options 12.1+
|
||||||
- ./webapp/custom:/srv/basex/lib/custom:ro # jars
|
- ./webapp/custom:/srv/basex/lib/custom:ro # jars
|
||||||
- ./webapp/lsp:/srv/basex/webapp/lsp
|
- ./webapp/lsp:/srv/basex/webapp/lsp
|
||||||
- ./webapp/static/clients:/srv/basex/webapp/static/clients:ro
|
- ./webapp/static/clients:/srv/basex/webapp/static/clients:ro
|
||||||
- ./webapp/lsp-manager:/srv/basex/webapp/lsp-manager
|
- ./webapp/lsp-manager:/srv/basex/webapp/lsp-manager
|
||||||
# - ./repo:/srv/basex/repo
|
# - ./repo:/srv/basex/repo
|
||||||
environment:
|
environment:
|
||||||
- "BASEX_JVM= -Dorg.basex.RESTXQERRORS=false -Dorg.basex.LOGEXCLUDE=/dba"
|
- "BASEX_JVM= -Dorg.basex.RESTXQERRORS=false -Dorg.basex.LOGEXCLUDE=/dba"
|
||||||
- "SERVER_OPTS= "
|
- "SERVER_OPTS= "
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
basex-lsp:
|
basex-lsp:
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,19 +1,19 @@
|
||||||
# Pipelines
|
# Pipelines
|
||||||
## Scripts
|
## Scripts
|
||||||
### Update local ebnf and fos catalog
|
### Update local ebnf and fos catalog
|
||||||
`scripts/update-sources.xq`
|
`scripts/update-sources.xq`
|
||||||
### Update xq4.java
|
### Update xq4.java
|
||||||
`scripts/rex.xq`
|
`scripts/rex.xq`
|
||||||
### Build `jar`
|
### Build `jar`
|
||||||
npm script `javac`
|
npm script `javac`
|
||||||
|
|
||||||
## Others
|
## Others
|
||||||
https://github.com/GuntherRademacher/rex-parser-generator/blob/main/docs/sample-grammars/XQuery-40.ebnf
|
https://github.com/GuntherRademacher/rex-parser-generator/blob/main/docs/sample-grammars/XQuery-40.ebnf
|
||||||
|
|
||||||
|
|
||||||
<any/><token>:=</token><any/>
|
<any/><token>:=</token><any/>
|
||||||
$p update
|
$p update
|
||||||
replace node //token[.=':='][preceding-siblings::*[1]/element()][following-siblings::*[1]/element()]with (' ',.,' ')...........................
|
replace node //token[.=':='][preceding-siblings::*[1]/element()][following-siblings::*[1]/element()]with (' ',.,' ')...........................
|
||||||
|
|
||||||
|
|
||||||
---------------Nico Verwer: SMAX (Separated Markup API for XML). SMAX (Separated Markup API for XML) https://github.com/nverwer/SMAX
|
---------------Nico Verwer: SMAX (Separated Markup API for XML). SMAX (Separated Markup API for XML) https://github.com/nverwer/SMAX
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
lsp websocket messages
|
lsp websocket messages
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"jsonrpc":"2.0","id":0,
|
{"jsonrpc":"2.0","id":0,
|
||||||
"method":"initialize",
|
"method":"initialize",
|
||||||
"params":{"capabilities":{"textDocument":{"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"synchronization":{"dynamicRegistration":true,"willSave":false,"didSave":false,"willSaveWaitUntil":false},"formatting":{"dynamicRegistration":true},"completion":{"dynamicRegistration":true,"completionItem":{"snippetSupport":true,"commitCharactersSupport":false,"documentationFormat":["markdown","plaintext"],"deprecatedSupport":false,"preselectSupport":false},"contextSupport":false},"signatureHelp":{"signatureInformation":{"documentationFormat":["markdown","plaintext"],"activeParameterSupport":true}},"documentHighlight":{"dynamicRegistration":true},"semanticTokens":{"multilineTokenSupport":false,"overlappingTokenSupport":false,"tokenTypes":[],"tokenModifiers":[],"formats":["relative"],"requests":{"full":{"delta":false},"range":true},"augmentsSyntaxTokens":true}},"workspace":{"didChangeConfiguration":{"dynamicRegistration":true}}},"processId":null,"rootUri":"","workspaceFolders":null}
|
"params":{"capabilities":{"textDocument":{"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"synchronization":{"dynamicRegistration":true,"willSave":false,"didSave":false,"willSaveWaitUntil":false},"formatting":{"dynamicRegistration":true},"completion":{"dynamicRegistration":true,"completionItem":{"snippetSupport":true,"commitCharactersSupport":false,"documentationFormat":["markdown","plaintext"],"deprecatedSupport":false,"preselectSupport":false},"contextSupport":false},"signatureHelp":{"signatureInformation":{"documentationFormat":["markdown","plaintext"],"activeParameterSupport":true}},"documentHighlight":{"dynamicRegistration":true},"semanticTokens":{"multilineTokenSupport":false,"overlappingTokenSupport":false,"tokenTypes":[],"tokenModifiers":[],"formats":["relative"],"requests":{"full":{"delta":false},"range":true},"augmentsSyntaxTokens":true}},"workspace":{"didChangeConfiguration":{"dynamicRegistration":true}}},"processId":null,"rootUri":"","workspaceFolders":null}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
<=
|
<=
|
||||||
{"jsonrpc":"2.0","id":0,
|
{"jsonrpc":"2.0","id":0,
|
||||||
"result":{"capabilities":{"textDocumentSync":2,"completionProvider":{"resolveProvider":false,"triggerCharacters":["\"",":"]},"hoverProvider":true,"documentSymbolProvider":true,"documentRangeFormattingProvider":false,"colorProvider":{},"foldingRangeProvider":true,"selectionRangeProvider":true,"documentLinkProvider":{}}}
|
"result":{"capabilities":{"textDocumentSync":2,"completionProvider":{"resolveProvider":false,"triggerCharacters":["\"",":"]},"hoverProvider":true,"documentSymbolProvider":true,"documentRangeFormattingProvider":false,"colorProvider":{},"foldingRangeProvider":true,"selectionRangeProvider":true,"documentLinkProvider":{}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
{"jsonrpc":"2.0","method":"initialized","params":{}}
|
{"jsonrpc":"2.0","method":"initialized","params":{}}
|
||||||
|
|
||||||
{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{}}}
|
{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{}}}
|
||||||
|
|
||||||
|
|
||||||
<=
|
<=
|
||||||
{"jsonrpc":"2.0",
|
{"jsonrpc":"2.0",
|
||||||
"method":"textDocument/publishDiagnostics",
|
"method":"textDocument/publishDiagnostics",
|
||||||
"params":{"uri":"session1.json","diagnostics":[]}
|
"params":{"uri":"session1.json","diagnostics":[]}
|
||||||
}
|
}
|
||||||
<=
|
<=
|
||||||
{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"session1.json","diagnostics":[{"range":{"start":{"line":2,"character":7},"end":{"line":2,"character":16}},"message":"Expected comma","severity":1,"code":514,"source":"json"}]}}
|
{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"session1.json","diagnostics":[{"range":{"start":{"line":2,"character":7},"end":{"line":2,"character":16}},"message":"Expected comma","severity":1,"code":514,"source":"json"}]}}
|
||||||
720
get-docker.sh
Normal file
720
get-docker.sh
Normal file
|
|
@ -0,0 +1,720 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
# Docker Engine for Linux installation script.
|
||||||
|
#
|
||||||
|
# This script is intended as a convenient way to configure docker's package
|
||||||
|
# repositories and to install Docker Engine, This script is not recommended
|
||||||
|
# for production environments. Before running this script, make yourself familiar
|
||||||
|
# with potential risks and limitations, and refer to the installation manual
|
||||||
|
# at https://docs.docker.com/engine/install/ for alternative installation methods.
|
||||||
|
#
|
||||||
|
# The script:
|
||||||
|
#
|
||||||
|
# - Requires `root` or `sudo` privileges to run.
|
||||||
|
# - Attempts to detect your Linux distribution and version and configure your
|
||||||
|
# package management system for you.
|
||||||
|
# - Doesn't allow you to customize most installation parameters.
|
||||||
|
# - Installs dependencies and recommendations without asking for confirmation.
|
||||||
|
# - Installs the latest stable release (by default) of Docker CLI, Docker Engine,
|
||||||
|
# Docker Buildx, Docker Compose, containerd, and runc. When using this script
|
||||||
|
# to provision a machine, this may result in unexpected major version upgrades
|
||||||
|
# of these packages. Always test upgrades in a test environment before
|
||||||
|
# deploying to your production systems.
|
||||||
|
# - Isn't designed to upgrade an existing Docker installation. When using the
|
||||||
|
# script to update an existing installation, dependencies may not be updated
|
||||||
|
# to the expected version, resulting in outdated versions.
|
||||||
|
#
|
||||||
|
# Source code is available at https://github.com/docker/docker-install/
|
||||||
|
#
|
||||||
|
# Usage
|
||||||
|
# ==============================================================================
|
||||||
|
#
|
||||||
|
# To install the latest stable versions of Docker CLI, Docker Engine, and their
|
||||||
|
# dependencies:
|
||||||
|
#
|
||||||
|
# 1. download the script
|
||||||
|
#
|
||||||
|
# $ curl -fsSL https://get.docker.com -o install-docker.sh
|
||||||
|
#
|
||||||
|
# 2. verify the script's content
|
||||||
|
#
|
||||||
|
# $ cat install-docker.sh
|
||||||
|
#
|
||||||
|
# 3. run the script with --dry-run to verify the steps it executes
|
||||||
|
#
|
||||||
|
# $ sh install-docker.sh --dry-run
|
||||||
|
#
|
||||||
|
# 4. run the script either as root, or using sudo to perform the installation.
|
||||||
|
#
|
||||||
|
# $ sudo sh install-docker.sh
|
||||||
|
#
|
||||||
|
# Command-line options
|
||||||
|
# ==============================================================================
|
||||||
|
#
|
||||||
|
# --version <VERSION>
|
||||||
|
# Use the --version option to install a specific version, for example:
|
||||||
|
#
|
||||||
|
# $ sudo sh install-docker.sh --version 23.0
|
||||||
|
#
|
||||||
|
# --channel <stable|test>
|
||||||
|
#
|
||||||
|
# Use the --channel option to install from an alternative installation channel.
|
||||||
|
# The following example installs the latest versions from the "test" channel,
|
||||||
|
# which includes pre-releases (alpha, beta, rc):
|
||||||
|
#
|
||||||
|
# $ sudo sh install-docker.sh --channel test
|
||||||
|
#
|
||||||
|
# Alternatively, use the script at https://test.docker.com, which uses the test
|
||||||
|
# channel as default.
|
||||||
|
#
|
||||||
|
# --mirror <Aliyun|AzureChinaCloud>
|
||||||
|
#
|
||||||
|
# Use the --mirror option to install from a mirror supported by this script.
|
||||||
|
# Available mirrors are "Aliyun" (https://mirrors.aliyun.com/docker-ce), and
|
||||||
|
# "AzureChinaCloud" (https://mirror.azure.cn/docker-ce), for example:
|
||||||
|
#
|
||||||
|
# $ sudo sh install-docker.sh --mirror AzureChinaCloud
|
||||||
|
#
|
||||||
|
# --setup-repo
|
||||||
|
#
|
||||||
|
# Use the --setup-repo option to configure Docker's package repositories without
|
||||||
|
# installing Docker packages. This is useful when you want to add the repository
|
||||||
|
# but install packages separately:
|
||||||
|
#
|
||||||
|
# $ sudo sh install-docker.sh --setup-repo
|
||||||
|
#
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
# Git commit from https://github.com/docker/docker-install when
|
||||||
|
# the script was uploaded (Should only be modified by upload job):
|
||||||
|
SCRIPT_COMMIT_SHA="7d96bd3c5235ab2121bcb855dd7b3f3f37128ed4"
|
||||||
|
|
||||||
|
# strip "v" prefix if present
|
||||||
|
VERSION="${VERSION#v}"
|
||||||
|
|
||||||
|
# The channel to install from:
|
||||||
|
# * stable
|
||||||
|
# * test
|
||||||
|
DEFAULT_CHANNEL_VALUE="stable"
|
||||||
|
if [ -z "$CHANNEL" ]; then
|
||||||
|
CHANNEL=$DEFAULT_CHANNEL_VALUE
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEFAULT_DOWNLOAD_URL="https://download.docker.com"
|
||||||
|
if [ -z "$DOWNLOAD_URL" ]; then
|
||||||
|
DOWNLOAD_URL=$DEFAULT_DOWNLOAD_URL
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEFAULT_REPO_FILE="docker-ce.repo"
|
||||||
|
if [ -z "$REPO_FILE" ]; then
|
||||||
|
REPO_FILE="$DEFAULT_REPO_FILE"
|
||||||
|
# Automatically default to a staging repo fora
|
||||||
|
# a staging download url (download-stage.docker.com)
|
||||||
|
case "$DOWNLOAD_URL" in
|
||||||
|
*-stage*) REPO_FILE="docker-ce-staging.repo";;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
mirror=''
|
||||||
|
DRY_RUN=${DRY_RUN:-}
|
||||||
|
REPO_ONLY=${REPO_ONLY:-0}
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--channel)
|
||||||
|
CHANNEL="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--dry-run)
|
||||||
|
DRY_RUN=1
|
||||||
|
;;
|
||||||
|
--mirror)
|
||||||
|
mirror="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--version)
|
||||||
|
VERSION="${2#v}"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--setup-repo)
|
||||||
|
REPO_ONLY=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--*)
|
||||||
|
echo "Illegal option $1"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift $(( $# > 0 ? 1 : 0 ))
|
||||||
|
done
|
||||||
|
|
||||||
|
case "$mirror" in
|
||||||
|
Aliyun)
|
||||||
|
DOWNLOAD_URL="https://mirrors.aliyun.com/docker-ce"
|
||||||
|
;;
|
||||||
|
AzureChinaCloud)
|
||||||
|
DOWNLOAD_URL="https://mirror.azure.cn/docker-ce"
|
||||||
|
;;
|
||||||
|
"")
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
>&2 echo "unknown mirror '$mirror': use either 'Aliyun', or 'AzureChinaCloud'."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$CHANNEL" in
|
||||||
|
stable|test)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
>&2 echo "unknown CHANNEL '$CHANNEL': use either stable or test."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
command_exists() {
|
||||||
|
command -v "$@" > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# version_gte checks if the version specified in $VERSION is at least the given
|
||||||
|
# SemVer (Maj.Minor[.Patch]), or CalVer (YY.MM) version.It returns 0 (success)
|
||||||
|
# if $VERSION is either unset (=latest) or newer or equal than the specified
|
||||||
|
# version, or returns 1 (fail) otherwise.
|
||||||
|
#
|
||||||
|
# examples:
|
||||||
|
#
|
||||||
|
# VERSION=23.0
|
||||||
|
# version_gte 23.0 // 0 (success)
|
||||||
|
# version_gte 20.10 // 0 (success)
|
||||||
|
# version_gte 19.03 // 0 (success)
|
||||||
|
# version_gte 26.1 // 1 (fail)
|
||||||
|
version_gte() {
|
||||||
|
if [ -z "$VERSION" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
version_compare "$VERSION" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# version_compare compares two version strings (either SemVer (Major.Minor.Path),
|
||||||
|
# or CalVer (YY.MM) version strings. It returns 0 (success) if version A is newer
|
||||||
|
# or equal than version B, or 1 (fail) otherwise. Patch releases and pre-release
|
||||||
|
# (-alpha/-beta) are not taken into account
|
||||||
|
#
|
||||||
|
# examples:
|
||||||
|
#
|
||||||
|
# version_compare 23.0.0 20.10 // 0 (success)
|
||||||
|
# version_compare 23.0 20.10 // 0 (success)
|
||||||
|
# version_compare 20.10 19.03 // 0 (success)
|
||||||
|
# version_compare 20.10 20.10 // 0 (success)
|
||||||
|
# version_compare 19.03 20.10 // 1 (fail)
|
||||||
|
version_compare() (
|
||||||
|
set +x
|
||||||
|
|
||||||
|
yy_a="$(echo "$1" | cut -d'.' -f1)"
|
||||||
|
yy_b="$(echo "$2" | cut -d'.' -f1)"
|
||||||
|
if [ "$yy_a" -lt "$yy_b" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [ "$yy_a" -gt "$yy_b" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
mm_a="$(echo "$1" | cut -d'.' -f2)"
|
||||||
|
mm_b="$(echo "$2" | cut -d'.' -f2)"
|
||||||
|
|
||||||
|
# trim leading zeros to accommodate CalVer
|
||||||
|
mm_a="${mm_a#0}"
|
||||||
|
mm_b="${mm_b#0}"
|
||||||
|
|
||||||
|
if [ "${mm_a:-0}" -lt "${mm_b:-0}" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
)
|
||||||
|
|
||||||
|
is_dry_run() {
|
||||||
|
if [ -z "$DRY_RUN" ]; then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
is_wsl() {
|
||||||
|
case "$(uname -r)" in
|
||||||
|
*microsoft* ) true ;; # WSL 2
|
||||||
|
*Microsoft* ) true ;; # WSL 1
|
||||||
|
* ) false;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
is_darwin() {
|
||||||
|
case "$(uname -s)" in
|
||||||
|
*darwin* ) true ;;
|
||||||
|
*Darwin* ) true ;;
|
||||||
|
* ) false;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
deprecation_notice() {
|
||||||
|
distro=$1
|
||||||
|
distro_version=$2
|
||||||
|
echo
|
||||||
|
printf "\033[91;1mDEPRECATION WARNING\033[0m\n"
|
||||||
|
printf " This Linux distribution (\033[1m%s %s\033[0m) reached end-of-life and is no longer supported by this script.\n" "$distro" "$distro_version"
|
||||||
|
echo " No updates or security fixes will be released for this distribution, and users are recommended"
|
||||||
|
echo " to upgrade to a currently maintained version of $distro."
|
||||||
|
echo
|
||||||
|
printf "Press \033[1mCtrl+C\033[0m now to abort this script, or wait for the installation to continue."
|
||||||
|
echo
|
||||||
|
sleep 10
|
||||||
|
}
|
||||||
|
|
||||||
|
get_distribution() {
|
||||||
|
lsb_dist=""
|
||||||
|
# Every system that we officially support has /etc/os-release
|
||||||
|
if [ -r /etc/os-release ]; then
|
||||||
|
lsb_dist="$(. /etc/os-release && echo "$ID")"
|
||||||
|
fi
|
||||||
|
# Returning an empty string here should be alright since the
|
||||||
|
# case statements don't act unless you provide an actual value
|
||||||
|
echo "$lsb_dist"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_docker_as_nonroot() {
|
||||||
|
if is_dry_run; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if command_exists docker && [ -e /var/run/docker.sock ]; then
|
||||||
|
(
|
||||||
|
set -x
|
||||||
|
$sh_c 'docker version'
|
||||||
|
) || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# intentionally mixed spaces and tabs here -- tabs are stripped by "<<-EOF", spaces are kept in the output
|
||||||
|
echo
|
||||||
|
echo "================================================================================"
|
||||||
|
echo
|
||||||
|
if version_gte "20.10"; then
|
||||||
|
echo "To run Docker as a non-privileged user, consider setting up the"
|
||||||
|
echo "Docker daemon in rootless mode for your user:"
|
||||||
|
echo
|
||||||
|
echo " dockerd-rootless-setuptool.sh install"
|
||||||
|
echo
|
||||||
|
echo "Visit https://docs.docker.com/go/rootless/ to learn about rootless mode."
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
echo "To run the Docker daemon as a fully privileged service, but granting non-root"
|
||||||
|
echo "users access, refer to https://docs.docker.com/go/daemon-access/"
|
||||||
|
echo
|
||||||
|
echo "WARNING: Access to the remote API on a privileged Docker daemon is equivalent"
|
||||||
|
echo " to root access on the host. Refer to the 'Docker daemon attack surface'"
|
||||||
|
echo " documentation for details: https://docs.docker.com/go/attack-surface/"
|
||||||
|
echo
|
||||||
|
echo "================================================================================"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if this is a forked Linux distro
|
||||||
|
check_forked() {
|
||||||
|
|
||||||
|
# Check for lsb_release command existence, it usually exists in forked distros
|
||||||
|
if command_exists lsb_release; then
|
||||||
|
# Check if the `-u` option is supported
|
||||||
|
set +e
|
||||||
|
lsb_release -a -u > /dev/null 2>&1
|
||||||
|
lsb_release_exit_code=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Check if the command has exited successfully, it means we're in a forked distro
|
||||||
|
if [ "$lsb_release_exit_code" = "0" ]; then
|
||||||
|
# Print info about current distro
|
||||||
|
cat <<-EOF
|
||||||
|
You're using '$lsb_dist' version '$dist_version'.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Get the upstream release info
|
||||||
|
lsb_dist=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'id' | cut -d ':' -f 2 | tr -d '[:space:]')
|
||||||
|
dist_version=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'codename' | cut -d ':' -f 2 | tr -d '[:space:]')
|
||||||
|
|
||||||
|
# Print info about upstream distro
|
||||||
|
cat <<-EOF
|
||||||
|
Upstream release is '$lsb_dist' version '$dist_version'.
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
if [ -r /etc/debian_version ] && [ "$lsb_dist" != "ubuntu" ] && [ "$lsb_dist" != "raspbian" ]; then
|
||||||
|
if [ "$lsb_dist" = "osmc" ]; then
|
||||||
|
# OSMC runs Raspbian
|
||||||
|
lsb_dist=raspbian
|
||||||
|
else
|
||||||
|
# We're Debian and don't even know it!
|
||||||
|
lsb_dist=debian
|
||||||
|
fi
|
||||||
|
dist_version="$(sed 's/\/.*//' /etc/debian_version | sed 's/\..*//')"
|
||||||
|
case "$dist_version" in
|
||||||
|
13)
|
||||||
|
dist_version="trixie"
|
||||||
|
;;
|
||||||
|
12)
|
||||||
|
dist_version="bookworm"
|
||||||
|
;;
|
||||||
|
11)
|
||||||
|
dist_version="bullseye"
|
||||||
|
;;
|
||||||
|
10)
|
||||||
|
dist_version="buster"
|
||||||
|
;;
|
||||||
|
9)
|
||||||
|
dist_version="stretch"
|
||||||
|
;;
|
||||||
|
8)
|
||||||
|
dist_version="jessie"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
do_install() {
|
||||||
|
echo "# Executing docker install script, commit: $SCRIPT_COMMIT_SHA"
|
||||||
|
|
||||||
|
if command_exists docker; then
|
||||||
|
cat >&2 <<-'EOF'
|
||||||
|
Warning: the "docker" command appears to already exist on this system.
|
||||||
|
|
||||||
|
If you already have Docker installed, this script can cause trouble, which is
|
||||||
|
why we're displaying this warning and provide the opportunity to cancel the
|
||||||
|
installation.
|
||||||
|
|
||||||
|
If you installed the current Docker package using this script and are using it
|
||||||
|
again to update Docker, you can ignore this message, but be aware that the
|
||||||
|
script resets any custom changes in the deb and rpm repo configuration
|
||||||
|
files to match the parameters passed to the script.
|
||||||
|
|
||||||
|
You may press Ctrl+C now to abort this script.
|
||||||
|
EOF
|
||||||
|
( set -x; sleep 20 )
|
||||||
|
fi
|
||||||
|
|
||||||
|
user="$(id -un 2>/dev/null || true)"
|
||||||
|
|
||||||
|
sh_c='sh -c'
|
||||||
|
if [ "$user" != 'root' ]; then
|
||||||
|
if command_exists sudo; then
|
||||||
|
sh_c='sudo -E sh -c'
|
||||||
|
elif command_exists su; then
|
||||||
|
sh_c='su -c'
|
||||||
|
else
|
||||||
|
cat >&2 <<-'EOF'
|
||||||
|
Error: this installer needs the ability to run commands as root.
|
||||||
|
We are unable to find either "sudo" or "su" available to make this happen.
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if is_dry_run; then
|
||||||
|
sh_c="echo"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# perform some very rudimentary platform detection
|
||||||
|
lsb_dist=$( get_distribution )
|
||||||
|
lsb_dist="$(echo "$lsb_dist" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
|
||||||
|
if is_wsl; then
|
||||||
|
echo
|
||||||
|
echo "WSL DETECTED: We recommend using Docker Desktop for Windows."
|
||||||
|
echo "Please get Docker Desktop from https://www.docker.com/products/docker-desktop/"
|
||||||
|
echo
|
||||||
|
cat >&2 <<-'EOF'
|
||||||
|
|
||||||
|
You may press Ctrl+C now to abort this script.
|
||||||
|
EOF
|
||||||
|
( set -x; sleep 20 )
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$lsb_dist" in
|
||||||
|
|
||||||
|
ubuntu)
|
||||||
|
if command_exists lsb_release; then
|
||||||
|
dist_version="$(lsb_release --codename | cut -f2)"
|
||||||
|
fi
|
||||||
|
if [ -z "$dist_version" ] && [ -r /etc/lsb-release ]; then
|
||||||
|
dist_version="$(. /etc/lsb-release && echo "$DISTRIB_CODENAME")"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
debian|raspbian)
|
||||||
|
dist_version="$(sed 's/\/.*//' /etc/debian_version | sed 's/\..*//')"
|
||||||
|
case "$dist_version" in
|
||||||
|
13)
|
||||||
|
dist_version="trixie"
|
||||||
|
;;
|
||||||
|
12)
|
||||||
|
dist_version="bookworm"
|
||||||
|
;;
|
||||||
|
11)
|
||||||
|
dist_version="bullseye"
|
||||||
|
;;
|
||||||
|
10)
|
||||||
|
dist_version="buster"
|
||||||
|
;;
|
||||||
|
9)
|
||||||
|
dist_version="stretch"
|
||||||
|
;;
|
||||||
|
8)
|
||||||
|
dist_version="jessie"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
|
||||||
|
centos|rhel)
|
||||||
|
if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then
|
||||||
|
dist_version="$(. /etc/os-release && echo "$VERSION_ID")"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
if command_exists lsb_release; then
|
||||||
|
dist_version="$(lsb_release --release | cut -f2)"
|
||||||
|
fi
|
||||||
|
if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then
|
||||||
|
dist_version="$(. /etc/os-release && echo "$VERSION_ID")"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Check if this is a forked Linux distro
|
||||||
|
check_forked
|
||||||
|
|
||||||
|
# Print deprecation warnings for distro versions that recently reached EOL,
|
||||||
|
# but may still be commonly used (especially LTS versions).
|
||||||
|
case "$lsb_dist.$dist_version" in
|
||||||
|
centos.8|centos.7|rhel.7)
|
||||||
|
deprecation_notice "$lsb_dist" "$dist_version"
|
||||||
|
;;
|
||||||
|
debian.buster|debian.stretch|debian.jessie)
|
||||||
|
deprecation_notice "$lsb_dist" "$dist_version"
|
||||||
|
;;
|
||||||
|
raspbian.buster|raspbian.stretch|raspbian.jessie)
|
||||||
|
deprecation_notice "$lsb_dist" "$dist_version"
|
||||||
|
;;
|
||||||
|
ubuntu.focal|ubuntu.bionic|ubuntu.xenial|ubuntu.trusty)
|
||||||
|
deprecation_notice "$lsb_dist" "$dist_version"
|
||||||
|
;;
|
||||||
|
ubuntu.oracular|ubuntu.mantic|ubuntu.lunar|ubuntu.kinetic|ubuntu.impish|ubuntu.hirsute|ubuntu.groovy|ubuntu.eoan|ubuntu.disco|ubuntu.cosmic)
|
||||||
|
deprecation_notice "$lsb_dist" "$dist_version"
|
||||||
|
;;
|
||||||
|
fedora.*)
|
||||||
|
if [ "$dist_version" -lt 41 ]; then
|
||||||
|
deprecation_notice "$lsb_dist" "$dist_version"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Run setup for each distro accordingly
|
||||||
|
case "$lsb_dist" in
|
||||||
|
ubuntu|debian|raspbian)
|
||||||
|
pre_reqs="ca-certificates curl"
|
||||||
|
apt_repo="deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] $DOWNLOAD_URL/linux/$lsb_dist $dist_version $CHANNEL"
|
||||||
|
(
|
||||||
|
if ! is_dry_run; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
$sh_c 'apt-get -qq update >/dev/null'
|
||||||
|
$sh_c "DEBIAN_FRONTEND=noninteractive apt-get -y -qq install $pre_reqs >/dev/null"
|
||||||
|
$sh_c 'install -m 0755 -d /etc/apt/keyrings'
|
||||||
|
$sh_c "curl -fsSL \"$DOWNLOAD_URL/linux/$lsb_dist/gpg\" -o /etc/apt/keyrings/docker.asc"
|
||||||
|
$sh_c "chmod a+r /etc/apt/keyrings/docker.asc"
|
||||||
|
$sh_c "echo \"$apt_repo\" > /etc/apt/sources.list.d/docker.list"
|
||||||
|
$sh_c 'apt-get -qq update >/dev/null'
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ "$REPO_ONLY" = "1" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
pkg_version=""
|
||||||
|
if [ -n "$VERSION" ]; then
|
||||||
|
if is_dry_run; then
|
||||||
|
echo "# WARNING: VERSION pinning is not supported in DRY_RUN"
|
||||||
|
else
|
||||||
|
# Will work for incomplete versions IE (17.12), but may not actually grab the "latest" if in the test channel
|
||||||
|
pkg_pattern="$(echo "$VERSION" | sed 's/-ce-/~ce~.*/g' | sed 's/-/.*/g')"
|
||||||
|
search_command="apt-cache madison docker-ce | grep '$pkg_pattern' | head -1 | awk '{\$1=\$1};1' | cut -d' ' -f 3"
|
||||||
|
pkg_version="$($sh_c "$search_command")"
|
||||||
|
echo "INFO: Searching repository for VERSION '$VERSION'"
|
||||||
|
echo "INFO: $search_command"
|
||||||
|
if [ -z "$pkg_version" ]; then
|
||||||
|
echo
|
||||||
|
echo "ERROR: '$VERSION' not found amongst apt-cache madison results"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if version_gte "18.09"; then
|
||||||
|
search_command="apt-cache madison docker-ce-cli | grep '$pkg_pattern' | head -1 | awk '{\$1=\$1};1' | cut -d' ' -f 3"
|
||||||
|
echo "INFO: $search_command"
|
||||||
|
cli_pkg_version="=$($sh_c "$search_command")"
|
||||||
|
fi
|
||||||
|
pkg_version="=$pkg_version"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
(
|
||||||
|
pkgs="docker-ce${pkg_version%=}"
|
||||||
|
if version_gte "18.09"; then
|
||||||
|
# older versions didn't ship the cli and containerd as separate packages
|
||||||
|
pkgs="$pkgs docker-ce-cli${cli_pkg_version%=} containerd.io"
|
||||||
|
fi
|
||||||
|
if version_gte "20.10"; then
|
||||||
|
pkgs="$pkgs docker-compose-plugin docker-ce-rootless-extras$pkg_version"
|
||||||
|
fi
|
||||||
|
if version_gte "23.0"; then
|
||||||
|
pkgs="$pkgs docker-buildx-plugin"
|
||||||
|
fi
|
||||||
|
if version_gte "28.2"; then
|
||||||
|
pkgs="$pkgs docker-model-plugin"
|
||||||
|
fi
|
||||||
|
if ! is_dry_run; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
$sh_c "DEBIAN_FRONTEND=noninteractive apt-get -y -qq install $pkgs >/dev/null"
|
||||||
|
)
|
||||||
|
echo_docker_as_nonroot
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
centos|fedora|rhel)
|
||||||
|
if [ "$(uname -m)" = "s390x" ]; then
|
||||||
|
echo "Effective v27.5, please consult RHEL distro statement for s390x support."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
repo_file_url="$DOWNLOAD_URL/linux/$lsb_dist/$REPO_FILE"
|
||||||
|
(
|
||||||
|
if ! is_dry_run; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
if command_exists dnf5; then
|
||||||
|
$sh_c "dnf -y -q --setopt=install_weak_deps=False install dnf-plugins-core"
|
||||||
|
$sh_c "dnf5 config-manager addrepo --overwrite --save-filename=docker-ce.repo --from-repofile='$repo_file_url'"
|
||||||
|
|
||||||
|
if [ "$CHANNEL" != "stable" ]; then
|
||||||
|
$sh_c "dnf5 config-manager setopt \"docker-ce-*.enabled=0\""
|
||||||
|
$sh_c "dnf5 config-manager setopt \"docker-ce-$CHANNEL.enabled=1\""
|
||||||
|
fi
|
||||||
|
$sh_c "dnf makecache"
|
||||||
|
elif command_exists dnf; then
|
||||||
|
$sh_c "dnf -y -q --setopt=install_weak_deps=False install dnf-plugins-core"
|
||||||
|
$sh_c "rm -f /etc/yum.repos.d/docker-ce.repo /etc/yum.repos.d/docker-ce-staging.repo"
|
||||||
|
$sh_c "dnf config-manager --add-repo $repo_file_url"
|
||||||
|
|
||||||
|
if [ "$CHANNEL" != "stable" ]; then
|
||||||
|
$sh_c "dnf config-manager --set-disabled \"docker-ce-*\""
|
||||||
|
$sh_c "dnf config-manager --set-enabled \"docker-ce-$CHANNEL\""
|
||||||
|
fi
|
||||||
|
$sh_c "dnf makecache"
|
||||||
|
else
|
||||||
|
$sh_c "yum -y -q install yum-utils"
|
||||||
|
$sh_c "rm -f /etc/yum.repos.d/docker-ce.repo /etc/yum.repos.d/docker-ce-staging.repo"
|
||||||
|
$sh_c "yum-config-manager --add-repo $repo_file_url"
|
||||||
|
|
||||||
|
if [ "$CHANNEL" != "stable" ]; then
|
||||||
|
$sh_c "yum-config-manager --disable \"docker-ce-*\""
|
||||||
|
$sh_c "yum-config-manager --enable \"docker-ce-$CHANNEL\""
|
||||||
|
fi
|
||||||
|
$sh_c "yum makecache"
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ "$REPO_ONLY" = "1" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
pkg_version=""
|
||||||
|
if command_exists dnf; then
|
||||||
|
pkg_manager="dnf"
|
||||||
|
pkg_manager_flags="-y -q --best"
|
||||||
|
else
|
||||||
|
pkg_manager="yum"
|
||||||
|
pkg_manager_flags="-y -q"
|
||||||
|
fi
|
||||||
|
if [ -n "$VERSION" ]; then
|
||||||
|
if is_dry_run; then
|
||||||
|
echo "# WARNING: VERSION pinning is not supported in DRY_RUN"
|
||||||
|
else
|
||||||
|
if [ "$lsb_dist" = "fedora" ]; then
|
||||||
|
pkg_suffix="fc$dist_version"
|
||||||
|
else
|
||||||
|
pkg_suffix="el"
|
||||||
|
fi
|
||||||
|
pkg_pattern="$(echo "$VERSION" | sed 's/-ce-/\\\\.ce.*/g' | sed 's/-/.*/g').*$pkg_suffix"
|
||||||
|
search_command="$pkg_manager list --showduplicates docker-ce | grep '$pkg_pattern' | tail -1 | awk '{print \$2}'"
|
||||||
|
pkg_version="$($sh_c "$search_command")"
|
||||||
|
echo "INFO: Searching repository for VERSION '$VERSION'"
|
||||||
|
echo "INFO: $search_command"
|
||||||
|
if [ -z "$pkg_version" ]; then
|
||||||
|
echo
|
||||||
|
echo "ERROR: '$VERSION' not found amongst $pkg_manager list results"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if version_gte "18.09"; then
|
||||||
|
# older versions don't support a cli package
|
||||||
|
search_command="$pkg_manager list --showduplicates docker-ce-cli | grep '$pkg_pattern' | tail -1 | awk '{print \$2}'"
|
||||||
|
cli_pkg_version="$($sh_c "$search_command" | cut -d':' -f 2)"
|
||||||
|
fi
|
||||||
|
# Cut out the epoch and prefix with a '-'
|
||||||
|
pkg_version="-$(echo "$pkg_version" | cut -d':' -f 2)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
(
|
||||||
|
pkgs="docker-ce$pkg_version"
|
||||||
|
if version_gte "18.09"; then
|
||||||
|
# older versions didn't ship the cli and containerd as separate packages
|
||||||
|
if [ -n "$cli_pkg_version" ]; then
|
||||||
|
pkgs="$pkgs docker-ce-cli-$cli_pkg_version containerd.io"
|
||||||
|
else
|
||||||
|
pkgs="$pkgs docker-ce-cli containerd.io"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if version_gte "20.10"; then
|
||||||
|
pkgs="$pkgs docker-compose-plugin docker-ce-rootless-extras$pkg_version"
|
||||||
|
fi
|
||||||
|
if version_gte "23.0"; then
|
||||||
|
pkgs="$pkgs docker-buildx-plugin docker-model-plugin"
|
||||||
|
fi
|
||||||
|
if ! is_dry_run; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
$sh_c "$pkg_manager $pkg_manager_flags install $pkgs"
|
||||||
|
)
|
||||||
|
echo_docker_as_nonroot
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
sles)
|
||||||
|
echo "Effective v27.5, please consult SLES distro statement for s390x support."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [ -z "$lsb_dist" ]; then
|
||||||
|
if is_darwin; then
|
||||||
|
echo
|
||||||
|
echo "ERROR: Unsupported operating system 'macOS'"
|
||||||
|
echo "Please get Docker Desktop from https://www.docker.com/products/docker-desktop"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
echo "ERROR: Unsupported distribution '$lsb_dist'"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# wrapped up in a function so that we have some protection against only getting
|
||||||
|
# half the file during "curl | sh"
|
||||||
|
do_install
|
||||||
4266
package-lock.json
generated
4266
package-lock.json
generated
File diff suppressed because it is too large
Load diff
74
package.json
74
package.json
|
|
@ -1,37 +1,37 @@
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/commands": "^6.10.0",
|
"@codemirror/commands": "^6.10.0",
|
||||||
"@codemirror/lang-javascript": "^6.2.4",
|
"@codemirror/lang-javascript": "^6.2.4",
|
||||||
"@codemirror/lang-markdown": "^6.5.0",
|
"@codemirror/lang-markdown": "^6.5.0",
|
||||||
"@codemirror/lang-xml": "^6.1.0",
|
"@codemirror/lang-xml": "^6.1.0",
|
||||||
"@codemirror/language-data": "^6.5.2",
|
"@codemirror/language-data": "^6.5.2",
|
||||||
"@codemirror/legacy-modes": "^6.5.2",
|
"@codemirror/legacy-modes": "^6.5.2",
|
||||||
"@codemirror/lint": "^6.9.1",
|
"@codemirror/lint": "^6.9.1",
|
||||||
"@codemirror/lsp-client": "^6.2.0",
|
"@codemirror/lsp-client": "^6.2.0",
|
||||||
"@codemirror/search": "^6.5.11",
|
"@codemirror/search": "^6.5.11",
|
||||||
"@codemirror/theme-one-dark": "^6.1.3",
|
"@codemirror/theme-one-dark": "^6.1.3",
|
||||||
"@codemirror/view": "^6.38.6",
|
"@codemirror/view": "^6.38.6",
|
||||||
"@quietui/quiet-browser": "^1.6.1",
|
"@quietui/quiet-browser": "^1.6.1",
|
||||||
"@replit/codemirror-minimap": "^0.5.2",
|
"@replit/codemirror-minimap": "^0.5.2",
|
||||||
"@zenfs/core": "^2.4.2",
|
"@zenfs/core": "^2.4.2",
|
||||||
"@zenfs/dom": "^1.2.5",
|
"@zenfs/dom": "^1.2.5",
|
||||||
"ace-builds": "^1.43.4",
|
"ace-builds": "^1.43.4",
|
||||||
"ace-linters": "^1.8.5",
|
"ace-linters": "^1.8.5",
|
||||||
"beercss": "^3.12.13"
|
"beercss": "^3.12.13"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||||
"@rollup/plugin-typescript": "^12.1.4",
|
"@rollup/plugin-typescript": "^12.1.4",
|
||||||
"minify": "^9.1.0",
|
"minify": "^9.1.0",
|
||||||
"rollup": "4",
|
"rollup": "4",
|
||||||
"rollup-plugin-tla": "^0.0.2"
|
"rollup-plugin-tla": "^0.0.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup cm6/index.js -m true -f iife -o dist/cm6.bundle.js -p node-resolve,tla --output.name cm6",
|
"build": "rollup cm6/index.js -m true -f iife -o dist/cm6.bundle.js -p node-resolve,tla --output.name cm6",
|
||||||
"lsp-build": "rollup bundles/cm6/lsp.js -m true -f iife -o webapp/static/clients/codemirror/lsp.bundle.js -p node-resolve,tla --output.name lsp",
|
"lsp-build": "rollup bundles/cm6/lsp.js -m true -f iife -o webapp/static/clients/codemirror/lsp.bundle.js -p node-resolve,tla --output.name lsp",
|
||||||
"lsp-min": "cd webapp/static/clients/codemirror && npx minify lsp.bundle.js > lsp.bundle.min.js ",
|
"lsp-min": "cd webapp/static/clients/codemirror && npx minify lsp.bundle.js > lsp.bundle.min.js ",
|
||||||
"min": "cd dist && npx minify cm6.bundle.js > cm6.bundle.min.js && npx minify lsp.bundle.js > lsp.bundle.min.js",
|
"min": "cd dist && npx minify cm6.bundle.js > cm6.bundle.min.js && npx minify lsp.bundle.js > lsp.bundle.min.js",
|
||||||
"javac": "cd bundles/grammar && javac --release 17 -cp %BASEX12%\\BaseX.jar -d build xq4.java && cd build && jar cf ../../../webapp/custom/xq4.jar . ",
|
"javac": "cd bundles/grammar && javac --release 17 -cp %BASEX12%\\BaseX.jar -d build xq4.java && cd build && jar cf ../../../webapp/custom/xq4.jar . ",
|
||||||
"railroad server": "cd C:/Users/mrwhe/apps/rr-2.5-java11 && java -jar rr.war -gui -port:5555"
|
"railroad server": "cd C:/Users/mrwhe/apps/rr-2.5-java11 && java -jar rr.war -gui -port:5555"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
|
|
||||||
import tla from 'rollup-plugin-tla';
|
import tla from 'rollup-plugin-tla';
|
||||||
import nodeResolve from 'rollup-node-resolve';
|
import nodeResolve from 'rollup-node-resolve';
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
input: 'src/editor.js',
|
input: 'src/editor.js',
|
||||||
output: {
|
output: {
|
||||||
format: 'iife',
|
format: 'iife',
|
||||||
dir: './dist',
|
dir: './dist',
|
||||||
file:"acm6.bundle.js",
|
file:"acm6.bundle.js",
|
||||||
name: `__Expose`,
|
name: `__Expose`,
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
},
|
},
|
||||||
plugins: [ nodeResolve(),tla()],
|
plugins: [ nodeResolve(),tla()],
|
||||||
});
|
});
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
|
|
@ -1,15 +1,15 @@
|
||||||
{
|
{
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"method": "textDocument/didChange",
|
"method": "textDocument/didChange",
|
||||||
"params": {
|
"params": {
|
||||||
"textDocument": {
|
"textDocument": {
|
||||||
"uri": "file:///some/file.xml",
|
"uri": "file:///some/file.xml",
|
||||||
"version": 1
|
"version": 1
|
||||||
},
|
},
|
||||||
"contentChanges": [
|
"contentChanges": [
|
||||||
{
|
{
|
||||||
"text": "3+1f"
|
"text": "3+1f"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
{
|
{
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"method": "textDocument/didChange",
|
"method": "textDocument/didChange",
|
||||||
"params": {
|
"params": {
|
||||||
"textDocument": {
|
"textDocument": {
|
||||||
"uri": "file:///some/file.xml",
|
"uri": "file:///some/file.xml",
|
||||||
"version": 2
|
"version": 2
|
||||||
},
|
},
|
||||||
"contentChanges": [
|
"contentChanges": [
|
||||||
{
|
{
|
||||||
"range": {
|
"range": {
|
||||||
"start": {
|
"start": {
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"character": 4
|
"character": 4
|
||||||
},
|
},
|
||||||
"end": {
|
"end": {
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"character": 4
|
"character": 4
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"text": "d"
|
"text": "d"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"method": "textDocument/didOpen",
|
"method": "textDocument/didOpen",
|
||||||
"params": {
|
"params": {
|
||||||
"textDocument": {
|
"textDocument": {
|
||||||
"uri": "file:///some/file.xml",
|
"uri": "file:///some/file.xml",
|
||||||
"languageId": "xml",
|
"languageId": "xml",
|
||||||
"text": "<foo at=42><bar>test</bar></foo>vvvbvbvbvbvbv\nvv\n\nvcccccccccccccc\n",
|
"text": "<foo at=42><bar>test</bar></foo>vvvbvbvbvbvbv\nvv\n\nvcccccccccccccc\n",
|
||||||
"version": 0
|
"version": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
{
|
{
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"method": "textDocument/hover",
|
"method": "textDocument/hover",
|
||||||
"params": {
|
"params": {
|
||||||
"textDocument": {
|
"textDocument": {
|
||||||
"uri": "file:///session1.json"
|
"uri": "file:///session1.json"
|
||||||
},
|
},
|
||||||
"position": {
|
"position": {
|
||||||
"line": 2,
|
"line": 2,
|
||||||
"character": 22
|
"character": 22
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,68 +1,68 @@
|
||||||
{
|
{
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "initialize",
|
"method": "initialize",
|
||||||
"params": {
|
"params": {
|
||||||
"processId": null,
|
"processId": null,
|
||||||
"clientInfo": {
|
"clientInfo": {
|
||||||
"name": "@codemirror/lsp-client"
|
"name": "@codemirror/lsp-client"
|
||||||
},
|
},
|
||||||
"rootUri": null,
|
"rootUri": null,
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"general": {
|
"general": {
|
||||||
"markdown": {
|
"markdown": {
|
||||||
"parser": "marked"
|
"parser": "marked"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"textDocument": {
|
"textDocument": {
|
||||||
"completion": {
|
"completion": {
|
||||||
"completionItem": {
|
"completionItem": {
|
||||||
"snippetSupport": true,
|
"snippetSupport": true,
|
||||||
"documentationFormat": [
|
"documentationFormat": [
|
||||||
"plaintext",
|
"plaintext",
|
||||||
"markdown"
|
"markdown"
|
||||||
],
|
],
|
||||||
"insertReplaceSupport": false
|
"insertReplaceSupport": false
|
||||||
},
|
},
|
||||||
"completionList": {
|
"completionList": {
|
||||||
"itemDefaults": [
|
"itemDefaults": [
|
||||||
"commitCharacters",
|
"commitCharacters",
|
||||||
"editRange",
|
"editRange",
|
||||||
"insertTextFormat"
|
"insertTextFormat"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"completionItemKind": {
|
"completionItemKind": {
|
||||||
"valueSet": []
|
"valueSet": []
|
||||||
},
|
},
|
||||||
"contextSupport": true
|
"contextSupport": true
|
||||||
},
|
},
|
||||||
"hover": {
|
"hover": {
|
||||||
"contentFormat": [
|
"contentFormat": [
|
||||||
"markdown",
|
"markdown",
|
||||||
"plaintext"
|
"plaintext"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"formatting": {},
|
"formatting": {},
|
||||||
"rename": {},
|
"rename": {},
|
||||||
"signatureHelp": {
|
"signatureHelp": {
|
||||||
"contextSupport": true,
|
"contextSupport": true,
|
||||||
"signatureInformation": {
|
"signatureInformation": {
|
||||||
"documentationFormat": [
|
"documentationFormat": [
|
||||||
"markdown",
|
"markdown",
|
||||||
"plaintext"
|
"plaintext"
|
||||||
],
|
],
|
||||||
"parameterInformation": {
|
"parameterInformation": {
|
||||||
"labelOffsetSupport": true
|
"labelOffsetSupport": true
|
||||||
},
|
},
|
||||||
"activeParameterSupport": true
|
"activeParameterSupport": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definition": {},
|
"definition": {},
|
||||||
"declaration": {},
|
"declaration": {},
|
||||||
"implementation": {},
|
"implementation": {},
|
||||||
"typeDefinition": {},
|
"typeDefinition": {},
|
||||||
"references": {}
|
"references": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,32 +1,32 @@
|
||||||
{
|
{
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"result": {
|
"result": {
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"textDocumentSync": 2,
|
"textDocumentSync": 2,
|
||||||
"completionProvider": {
|
"completionProvider": {
|
||||||
"resolveProvider": false,
|
"resolveProvider": false,
|
||||||
"triggerCharacters": [
|
"triggerCharacters": [
|
||||||
"\"",
|
"\"",
|
||||||
":"
|
":"
|
||||||
],
|
],
|
||||||
"documentSelector": [
|
"documentSelector": [
|
||||||
{
|
{
|
||||||
"language": "xquery"
|
"language": "xquery"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hoverProvider": true,
|
"hoverProvider": true,
|
||||||
"documentSymbolProvider": true,
|
"documentSymbolProvider": true,
|
||||||
"documentRangeFormattingProvider": false,
|
"documentRangeFormattingProvider": false,
|
||||||
"colorProvider": {},
|
"colorProvider": {},
|
||||||
"foldingRangeProvider": true,
|
"foldingRangeProvider": true,
|
||||||
"selectionRangeProvider": true,
|
"selectionRangeProvider": true,
|
||||||
"documentLinkProvider": {},
|
"documentLinkProvider": {},
|
||||||
"serverInfo": {
|
"serverInfo": {
|
||||||
"name": "My Custom Language Server",
|
"name": "My Custom Language Server",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"jsonrpc": "2.0"
|
"jsonrpc": "2.0"
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
module namespace wsa = 'app/sockets';
|
module namespace wsa = 'app/sockets';
|
||||||
import module namespace ws="http://basex.org/modules/ws";
|
import module namespace ws="http://basex.org/modules/ws";
|
||||||
|
|
||||||
|
|
||||||
declare function wsa:wsids()
|
declare function wsa:wsids()
|
||||||
as xs:string*
|
as xs:string*
|
||||||
{
|
{
|
||||||
ws:ids()
|
ws:ids()
|
||||||
};
|
};
|
||||||
|
|
||||||
declare %rest:path('/app/api/sockets')
|
declare %rest:path('/app/api/sockets')
|
||||||
function wsa:list()
|
function wsa:list()
|
||||||
as element(ul)
|
as element(ul)
|
||||||
{
|
{
|
||||||
<ul>{
|
<ul>{
|
||||||
wsa:wsids()!<li><a href="/app/sockets/{.}">{.}</a></li>
|
wsa:wsids()!<li><a href="/app/sockets/{.}">{.}</a></li>
|
||||||
}</ul>
|
}</ul>
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
@ -1,26 +1,26 @@
|
||||||
module namespace _ = 'app/error-reporting';
|
module namespace _ = 'app/error-reporting';
|
||||||
import module namespace cm = "app/cm" at "common.xqm";
|
import module namespace cm = "app/cm" at "common.xqm";
|
||||||
|
|
||||||
|
|
||||||
declare
|
declare
|
||||||
%rest:error("*")
|
%rest:error("*")
|
||||||
%rest:error-param("code", "{$code}")
|
%rest:error-param("code", "{$code}")
|
||||||
%rest:error-param("description", "{$description}")
|
%rest:error-param("description", "{$description}")
|
||||||
%rest:error-param("value", "{$value}")
|
%rest:error-param("value", "{$value}")
|
||||||
%rest:error-param("module", "{$module}")
|
%rest:error-param("module", "{$module}")
|
||||||
%rest:error-param("line-number", "{$line-number}")
|
%rest:error-param("line-number", "{$line-number}")
|
||||||
%rest:error-param("column-number","{$column-number}")
|
%rest:error-param("column-number","{$column-number}")
|
||||||
%rest:error-param("additional", "{$additional}")
|
%rest:error-param("additional", "{$additional}")
|
||||||
function _:error($code,$description,$value,
|
function _:error($code,$description,$value,
|
||||||
$module,$line-number,$column-number,$additional) {
|
$module,$line-number,$column-number,$additional) {
|
||||||
let $err:=map{"code":$code, "description":$description,
|
let $err:=map{"code":$code, "description":$description,
|
||||||
"value": _:format($value), "module": $module,
|
"value": _:format($value), "module": $module,
|
||||||
"line-number": $line-number, "column-number": $column-number,
|
"line-number": $line-number, "column-number": $column-number,
|
||||||
"additional": _:format($additional)}
|
"additional": _:format($additional)}
|
||||||
return cm:htmx2("error.htm", $err)
|
return cm:htmx2("error.htm", $err)
|
||||||
};
|
};
|
||||||
|
|
||||||
declare function _:format($item)
|
declare function _:format($item)
|
||||||
as xs:string{
|
as xs:string{
|
||||||
serialize($item,map{"method":"basex"})
|
serialize($item,map{"method":"basex"})
|
||||||
};
|
};
|
||||||
|
|
@ -1,102 +1,102 @@
|
||||||
xquery version '3.1';
|
xquery version '3.1';
|
||||||
(:~ save conversion outputs to file
|
(:~ save conversion outputs to file
|
||||||
ensures target folders created
|
ensures target folders created
|
||||||
save multiple docs when root <wrapper> found
|
save multiple docs when root <wrapper> found
|
||||||
optionally serialize XML with default namespace
|
optionally serialize XML with default namespace
|
||||||
@author quodatum Andy Bunce
|
@author quodatum Andy Bunce
|
||||||
:)
|
:)
|
||||||
module namespace outlet = 'urn:conversion:outlet';
|
module namespace outlet = 'urn:conversion:outlet';
|
||||||
|
|
||||||
(: serialization options
|
(: serialization options
|
||||||
key is arbitary name, value is BaseX serialization option map
|
key is arbitary name, value is BaseX serialization option map
|
||||||
for xml serializations the non-standard 'ns' option supplies a namespace to use as default ' :)
|
for xml serializations the non-standard 'ns' option supplies a namespace to use as default ' :)
|
||||||
declare variable $outlet:serial:=map{
|
declare variable $outlet:serial:=map{
|
||||||
"xvrl": map{"method":"xml","ns":"http://www.xproc.org/ns/xvrl"},
|
"xvrl": map{"method":"xml","ns":"http://www.xproc.org/ns/xvrl"},
|
||||||
"docbook":map{"method":"xml","ns":"http://docbook.org/ns/docbook"},
|
"docbook":map{"method":"xml","ns":"http://docbook.org/ns/docbook"},
|
||||||
"csv": map{"method":"text"},
|
"csv": map{"method":"text"},
|
||||||
"xml": map{"method":"xml"}
|
"xml": map{"method":"xml"}
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~save $doc to $dest unless empty,will create directories as required
|
(:~save $doc to $dest unless empty,will create directories as required
|
||||||
@param $opts serialization options and ns to set a default namespace :)
|
@param $opts serialization options and ns to set a default namespace :)
|
||||||
declare function outlet:save($doc as item(),$dest as xs:string?,$opts as map(*)?)
|
declare function outlet:save($doc as item(),$dest as xs:string?,$opts as map(*)?)
|
||||||
as xs:string?{
|
as xs:string?{
|
||||||
if (exists($dest))
|
if (exists($dest))
|
||||||
then
|
then
|
||||||
let $doc:=if($opts?ns)
|
let $doc:=if($opts?ns)
|
||||||
then outlet:change-element-ns-deep($doc,$opts?ns,"")
|
then outlet:change-element-ns-deep($doc,$opts?ns,"")
|
||||||
else $doc
|
else $doc
|
||||||
return (
|
return (
|
||||||
file:create-dir(file:parent($dest)),
|
file:create-dir(file:parent($dest)),
|
||||||
file:write($dest,$doc,map:remove($opts,"ns")),
|
file:write($dest,$doc,map:remove($opts,"ns")),
|
||||||
$dest
|
$dest
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ save file or files if node is wrapper
|
(:~ save file or files if node is wrapper
|
||||||
@return paths to saved files
|
@return paths to saved files
|
||||||
:)
|
:)
|
||||||
declare function outlet:save-wrapper($doc as item(),$dest as xs:string?,$opts as map(*)?)
|
declare function outlet:save-wrapper($doc as item(),$dest as xs:string?,$opts as map(*)?)
|
||||||
as xs:string*{
|
as xs:string*{
|
||||||
if ($doc/wrapper)
|
if ($doc/wrapper)
|
||||||
then $doc/wrapper/result! outlet:save(*,file:resolve-path(@href,$dest),$opts)
|
then $doc/wrapper/result! outlet:save(*,file:resolve-path(@href,$dest),$opts)
|
||||||
else outlet:save($doc,$dest,$opts)
|
else outlet:save($doc,$dest,$opts)
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ from functx http://www.xqueryfunctions.com/xq/functx_change-element-ns-deep.html :)
|
(:~ from functx http://www.xqueryfunctions.com/xq/functx_change-element-ns-deep.html :)
|
||||||
declare function outlet:change-element-ns-deep
|
declare function outlet:change-element-ns-deep
|
||||||
( $nodes as node()* ,
|
( $nodes as node()* ,
|
||||||
$newns as xs:string ,
|
$newns as xs:string ,
|
||||||
$prefix as xs:string ) as node()* {
|
$prefix as xs:string ) as node()* {
|
||||||
|
|
||||||
for $node in $nodes
|
for $node in $nodes
|
||||||
return if ($node instance of element())
|
return if ($node instance of element())
|
||||||
then (element
|
then (element
|
||||||
{QName ($newns,
|
{QName ($newns,
|
||||||
concat($prefix,
|
concat($prefix,
|
||||||
if ($prefix = '')
|
if ($prefix = '')
|
||||||
then ''
|
then ''
|
||||||
else ':',
|
else ':',
|
||||||
local-name($node)))}
|
local-name($node)))}
|
||||||
{$node/@*,
|
{$node/@*,
|
||||||
outlet:change-element-ns-deep($node/node(),
|
outlet:change-element-ns-deep($node/node(),
|
||||||
$newns, $prefix)})
|
$newns, $prefix)})
|
||||||
else if ($node instance of document-node())
|
else if ($node instance of document-node())
|
||||||
then outlet:change-element-ns-deep($node/node(),
|
then outlet:change-element-ns-deep($node/node(),
|
||||||
$newns, $prefix)
|
$newns, $prefix)
|
||||||
else $node
|
else $node
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
(:~ @see https://stackoverflow.com/a/8600987/3210344 :)
|
(:~ @see https://stackoverflow.com/a/8600987/3210344 :)
|
||||||
declare function outlet:remove-prefixes($node as node(), $prefixes as xs:string*)
|
declare function outlet:remove-prefixes($node as node(), $prefixes as xs:string*)
|
||||||
as node(){
|
as node(){
|
||||||
typeswitch ($node)
|
typeswitch ($node)
|
||||||
case element()
|
case element()
|
||||||
return
|
return
|
||||||
if ($prefixes = ('#all', prefix-from-QName(node-name($node)))) then
|
if ($prefixes = ('#all', prefix-from-QName(node-name($node)))) then
|
||||||
element {QName(namespace-uri($node), local-name($node))} {
|
element {QName(namespace-uri($node), local-name($node))} {
|
||||||
$node/@*,
|
$node/@*,
|
||||||
$node/node()/outlet:remove-prefixes(., $prefixes)
|
$node/node()/outlet:remove-prefixes(., $prefixes)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
element {node-name($node)} {
|
element {node-name($node)} {
|
||||||
$node/@*,
|
$node/@*,
|
||||||
$node/node()/outlet:remove-prefixes(., $prefixes)
|
$node/node()/outlet:remove-prefixes(., $prefixes)
|
||||||
}
|
}
|
||||||
case document-node()
|
case document-node()
|
||||||
return
|
return
|
||||||
document {
|
document {
|
||||||
$node/node()/outlet:remove-prefixes(., $prefixes)
|
$node/node()/outlet:remove-prefixes(., $prefixes)
|
||||||
}
|
}
|
||||||
default
|
default
|
||||||
return $node
|
return $node
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ relative file paths below folder $path, matching $selector :)
|
(:~ relative file paths below folder $path, matching $selector :)
|
||||||
declare function outlet:select($path as xs:string,$selector as map(xs:string,item()*))
|
declare function outlet:select($path as xs:string,$selector as map(xs:string,item()*))
|
||||||
as xs:string*
|
as xs:string*
|
||||||
{
|
{
|
||||||
file:list($path,true(),$selector?pattern)
|
file:list($path,true(),$selector?pattern)
|
||||||
[some $i in $selector?include satisfies contains(.,$i)]
|
[some $i in $selector?include satisfies contains(.,$i)]
|
||||||
[every $x in $selector?exclude satisfies not(contains(.,$x))]
|
[every $x in $selector?exclude satisfies not(contains(.,$x))]
|
||||||
};
|
};
|
||||||
|
|
@ -1,199 +1,199 @@
|
||||||
xquery version '3.1';
|
xquery version '3.1';
|
||||||
(:~
|
(:~
|
||||||
Library to manage running multiple jobs using BaseX job:eval,
|
Library to manage running multiple jobs using BaseX job:eval,
|
||||||
where the jobs are the execution of one function for a set of arguments
|
where the jobs are the execution of one function for a set of arguments
|
||||||
|
|
||||||
The function will have signature `fn($key as xs:string) as element()`
|
The function will have signature `fn($key as xs:string) as element()`
|
||||||
The function will typically create outputs and have side effects.
|
The function will typically create outputs and have side effects.
|
||||||
|
|
||||||
State information is persisted with the storage module, using the key '_wrangle'
|
State information is persisted with the storage module, using the key '_wrangle'
|
||||||
It is a map{$wid: {"jobs":}}
|
It is a map{$wid: {"jobs":}}
|
||||||
requires basex 10+
|
requires basex 10+
|
||||||
@licence BSD
|
@licence BSD
|
||||||
@author: quodatum
|
@author: quodatum
|
||||||
@date: 2023/02/12
|
@date: 2023/02/12
|
||||||
:)
|
:)
|
||||||
module namespace wrangle = 'urn:quodatum:wrangler';
|
module namespace wrangle = 'urn:quodatum:wrangler';
|
||||||
(:~ semantic version :)
|
(:~ semantic version :)
|
||||||
declare variable $wrangle:version:="1.0.0";
|
declare variable $wrangle:version:="1.0.0";
|
||||||
(:~ used in bindings to indicate a wrangle job and as store key :)
|
(:~ used in bindings to indicate a wrangle job and as store key :)
|
||||||
declare variable $wrangle:id:="_wrangle";
|
declare variable $wrangle:id:="_wrangle";
|
||||||
|
|
||||||
(:~
|
(:~
|
||||||
submit wrangle jobs for each $item
|
submit wrangle jobs for each $item
|
||||||
@param wrangle data{xq:...,bindings:..}
|
@param wrangle data{xq:...,bindings:..}
|
||||||
@return unique id for the job set
|
@return unique id for the job set
|
||||||
:)
|
:)
|
||||||
declare function wrangle:queue($items as item()*,$wrangle as map(*))
|
declare function wrangle:queue($items as item()*,$wrangle as map(*))
|
||||||
as xs:string{
|
as xs:string{
|
||||||
let $wid := random:uuid()
|
let $wid := random:uuid()
|
||||||
let $jobs := $items!job:eval($wrangle?xq,
|
let $jobs := $items!job:eval($wrangle?xq,
|
||||||
map:merge(($wrangle?bindings(.),map:entry($wrangle:id,$wid))),
|
map:merge(($wrangle?bindings(.),map:entry($wrangle:id,$wid))),
|
||||||
map{"cache":true()}
|
map{"cache":true()}
|
||||||
)
|
)
|
||||||
|
|
||||||
let $this := map:entry($wid,map:entry("jobs",$jobs!map:entry(.,
|
let $this := map:entry($wid,map:entry("jobs",$jobs!map:entry(.,
|
||||||
map{
|
map{
|
||||||
"complete":false(),
|
"complete":false(),
|
||||||
"details":job:list-details(.)
|
"details":job:list-details(.)
|
||||||
})))
|
})))
|
||||||
|
|
||||||
let $_:=store:put($wrangle:id,map:merge((($this,wrangle:store()))))
|
let $_:=store:put($wrangle:id,map:merge((($this,wrangle:store()))))
|
||||||
return $wid
|
return $wid
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ active wrangle ids :)
|
(:~ active wrangle ids :)
|
||||||
declare function wrangle:active()
|
declare function wrangle:active()
|
||||||
as xs:string*{
|
as xs:string*{
|
||||||
job:list()!job:bindings(.)?($wrangle:id)=>distinct-values()
|
job:list()!job:bindings(.)?($wrangle:id)=>distinct-values()
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ known wrangles :)
|
(:~ known wrangles :)
|
||||||
declare function wrangle:list()
|
declare function wrangle:list()
|
||||||
as xs:string*{
|
as xs:string*{
|
||||||
wrangle:store()=>map:keys()
|
wrangle:store()=>map:keys()
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ details for $wid wrangle :)
|
(:~ details for $wid wrangle :)
|
||||||
declare function wrangle:list-details($wid as xs:string)
|
declare function wrangle:list-details($wid as xs:string)
|
||||||
as map(*){
|
as map(*){
|
||||||
wrangle:store()=>map:get($wid)
|
wrangle:store()=>map:get($wid)
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ all wrangled jobs :)
|
(:~ all wrangled jobs :)
|
||||||
declare function wrangle:job-list()
|
declare function wrangle:job-list()
|
||||||
as xs:string*{
|
as xs:string*{
|
||||||
job:list()[job:bindings(.)=>map:contains($wrangle:id)]
|
job:list()[job:bindings(.)=>map:contains($wrangle:id)]
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ jobs for wrangle id :)
|
(:~ jobs for wrangle id :)
|
||||||
declare function wrangle:job-list($wid as xs:string)
|
declare function wrangle:job-list($wid as xs:string)
|
||||||
as xs:string*{
|
as xs:string*{
|
||||||
job:list()[job:bindings(.)?($wrangle:id) eq $wid]
|
job:list()[job:bindings(.)?($wrangle:id) eq $wid]
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ is wrangle id finished (or unknown) :)
|
(:~ is wrangle id finished (or unknown) :)
|
||||||
declare function wrangle:finished($wid as xs:string)
|
declare function wrangle:finished($wid as xs:string)
|
||||||
as xs:string*{
|
as xs:string*{
|
||||||
every $job in job:list()[job:bindings(.)?($wrangle:id) eq $wid] satisfies job:finished($job)
|
every $job in job:list()[job:bindings(.)?($wrangle:id) eq $wid] satisfies job:finished($job)
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ wait wrangle id finished (or unknown) :)
|
(:~ wait wrangle id finished (or unknown) :)
|
||||||
declare function wrangle:wait($wid as xs:string)
|
declare function wrangle:wait($wid as xs:string)
|
||||||
as empty-sequence(){
|
as empty-sequence(){
|
||||||
let $done:=every $job in job:list()[job:bindings(.)?($wrangle:id) eq $wid]
|
let $done:=every $job in job:list()[job:bindings(.)?($wrangle:id) eq $wid]
|
||||||
satisfies empty(job:wait($job))
|
satisfies empty(job:wait($job))
|
||||||
return if($done) then ()
|
return if($done) then ()
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ cancel wrangle id :)
|
(:~ cancel wrangle id :)
|
||||||
declare function wrangle:remove($wid as xs:string)
|
declare function wrangle:remove($wid as xs:string)
|
||||||
as empty-sequence(){
|
as empty-sequence(){
|
||||||
job:list()[job:bindings(.)?($wrangle:id) eq $wid]!job:remove(.),
|
job:list()[job:bindings(.)?($wrangle:id) eq $wid]!job:remove(.),
|
||||||
store:put($wrangle:id,wrangle:store()=>map:remove($wid))
|
store:put($wrangle:id,wrangle:store()=>map:remove($wid))
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ tally of non-zero job status for $wid "scheduled", "queued", "running", "cached" :)
|
(:~ tally of non-zero job status for $wid "scheduled", "queued", "running", "cached" :)
|
||||||
declare function wrangle:status($wid as xs:string)
|
declare function wrangle:status($wid as xs:string)
|
||||||
as map(*){
|
as map(*){
|
||||||
wrangle:job-list($wid)!job:list-details(.)/@state/string()
|
wrangle:job-list($wid)!job:list-details(.)/@state/string()
|
||||||
=>fold-left(map{},wrangle:tally-count#2)
|
=>fold-left(map{},wrangle:tally-count#2)
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ job-results with no error as sequence:)
|
(:~ job-results with no error as sequence:)
|
||||||
declare function wrangle:results($wid as xs:string)
|
declare function wrangle:results($wid as xs:string)
|
||||||
as item()*{
|
as item()*{
|
||||||
wrangle:job-list($wid)!wrangle:job-result(.)[not(?error)]?result
|
wrangle:job-list($wid)!wrangle:job-result(.)[not(?error)]?result
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ error counts keyed on $err:code :)
|
(:~ error counts keyed on $err:code :)
|
||||||
declare function wrangle:errors($wid as xs:string)
|
declare function wrangle:errors($wid as xs:string)
|
||||||
as map(*){
|
as map(*){
|
||||||
wrangle:job-list($wid)!wrangle:job-result(.)[?error]?result?code!string()
|
wrangle:job-list($wid)!wrangle:job-result(.)[?error]?result?code!string()
|
||||||
=>fold-left(map{},wrangle:tally-count#2)
|
=>fold-left(map{},wrangle:tally-count#2)
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ key is $err:code values are joblists :)
|
(:~ key is $err:code values are joblists :)
|
||||||
declare function wrangle:jobs-by-error($wid as xs:string)
|
declare function wrangle:jobs-by-error($wid as xs:string)
|
||||||
as map(*){
|
as map(*){
|
||||||
(for $jobId in wrangle:job-list($wid)
|
(for $jobId in wrangle:job-list($wid)
|
||||||
let $result:=wrangle:job-result($jobId)[?error]
|
let $result:=wrangle:job-result($jobId)[?error]
|
||||||
where exists($result)
|
where exists($result)
|
||||||
return map:entry($result?result?code!string(),$jobId)
|
return map:entry($result?result?code!string(),$jobId)
|
||||||
)
|
)
|
||||||
=> map:merge( map{"duplicates":"combine"})
|
=> map:merge( map{"duplicates":"combine"})
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ return key for job:)
|
(:~ return key for job:)
|
||||||
declare function wrangle:job-key($jobId as xs:string)
|
declare function wrangle:job-key($jobId as xs:string)
|
||||||
as xs:string{
|
as xs:string{
|
||||||
let $b:=job:bindings($jobId)
|
let $b:=job:bindings($jobId)
|
||||||
return $b?(map:keys($b)[. ne $wrangle:id])
|
return $b?(map:keys($b)[. ne $wrangle:id])
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ return map from peek at result:)
|
(:~ return map from peek at result:)
|
||||||
declare function wrangle:job-result($jobId as xs:string)
|
declare function wrangle:job-result($jobId as xs:string)
|
||||||
as map(*){
|
as map(*){
|
||||||
try{
|
try{
|
||||||
map{
|
map{
|
||||||
"error":false(),
|
"error":false(),
|
||||||
"result": job:result($jobId,map{"keep":true()})
|
"result": job:result($jobId,map{"keep":true()})
|
||||||
}
|
}
|
||||||
}catch *{
|
}catch *{
|
||||||
map{
|
map{
|
||||||
"error":true(),
|
"error":true(),
|
||||||
"result": map{"description": $err:description,
|
"result": map{"description": $err:description,
|
||||||
"code": $err:code,
|
"code": $err:code,
|
||||||
"line": $err:column-number,
|
"line": $err:column-number,
|
||||||
"additional": $err:additional,
|
"additional": $err:additional,
|
||||||
"value":$err:value
|
"value":$err:value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ XQuery for background service :)
|
(:~ XQuery for background service :)
|
||||||
declare function wrangle:service()
|
declare function wrangle:service()
|
||||||
as xs:string{
|
as xs:string{
|
||||||
``[
|
``[
|
||||||
import module namespace wrangle = 'urn:quodatum:wrangler:v1'; at "`{ static-base-uri() }`";
|
import module namespace wrangle = 'urn:quodatum:wrangler:v1'; at "`{ static-base-uri() }`";
|
||||||
let $done:=wrangle:job-list()[job:finished(.)]
|
let $done:=wrangle:job-list()[job:finished(.)]
|
||||||
if(exists($done))
|
if(exists($done))
|
||||||
then let $w:=store:get($wrangle:id)
|
then let $w:=store:get($wrangle:id)
|
||||||
for $job in $done
|
for $job in $done
|
||||||
group by $wid= job:bindings($job)?($wrangle:id)
|
group by $wid= job:bindings($job)?($wrangle:id)
|
||||||
for $job in $job
|
for $job in $job
|
||||||
let $_:=store:put($wrangle:id)
|
let $_:=store:put($wrangle:id)
|
||||||
]``
|
]``
|
||||||
|
|
||||||
};
|
};
|
||||||
(:~ schedule as service :)
|
(:~ schedule as service :)
|
||||||
declare function wrangle:schedule-service()
|
declare function wrangle:schedule-service()
|
||||||
as xs:string{
|
as xs:string{
|
||||||
wrangle:service()
|
wrangle:service()
|
||||||
=>job:eval((), map { 'id':$wrangle:id, 'service':true(),
|
=>job:eval((), map { 'id':$wrangle:id, 'service':true(),
|
||||||
'interval': 'PT1S','log': $wrangle:id})
|
'interval': 'PT1S','log': $wrangle:id})
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ cached data as map :)
|
(:~ cached data as map :)
|
||||||
declare function wrangle:store()
|
declare function wrangle:store()
|
||||||
as map(*){
|
as map(*){
|
||||||
store:get-or-put($wrangle:id,function(){map{}})
|
store:get-or-put($wrangle:id,function(){map{}})
|
||||||
};
|
};
|
||||||
|
|
||||||
(:~ @return map string->count for fold-left :)
|
(:~ @return map string->count for fold-left :)
|
||||||
declare %private function wrangle:tally-count($r as map(*),$this as xs:string)
|
declare %private function wrangle:tally-count($r as map(*),$this as xs:string)
|
||||||
as map(*){
|
as map(*){
|
||||||
map:merge(
|
map:merge(
|
||||||
(map:entry($this,if(map:contains($r,$this)) then $r($this)+1 else 1),$r),
|
(map:entry($this,if(map:contains($r,$this)) then $r($this)+1 else 1),$r),
|
||||||
map{"duplicates":"use-first"}
|
map{"duplicates":"use-first"}
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
(:~ @return map string->(string*) for fold-left :)
|
(:~ @return map string->(string*) for fold-left :)
|
||||||
declare %private function wrangle:tally-list($r as map(*),$key as xs:string,$value as xs:string)
|
declare %private function wrangle:tally-list($r as map(*),$key as xs:string,$value as xs:string)
|
||||||
as map(*){
|
as map(*){
|
||||||
map:merge(
|
map:merge(
|
||||||
(map:entry($key,$value),$r),
|
(map:entry($key,$value),$r),
|
||||||
map{"duplicates":"combine"}
|
map{"duplicates":"combine"}
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
<!DOCTYPE HTML5>
|
<!DOCTYPE HTML5>
|
||||||
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
layout:decorate="~{layout.htm}">
|
layout:decorate="~{layout.htm}">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>dev</title>
|
<title>dev</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div layout:fragment="content">
|
<div layout:fragment="content">
|
||||||
<sl-breadcrumb>
|
<sl-breadcrumb>
|
||||||
<sl-breadcrumb-item href="/app/dev">DEV</sl-breadcrumb-item>
|
<sl-breadcrumb-item href="/app/dev">DEV</sl-breadcrumb-item>
|
||||||
<sl-breadcrumb-item>dba</sl-breadcrumb-item>
|
<sl-breadcrumb-item>dba</sl-breadcrumb-item>
|
||||||
|
|
||||||
</sl-breadcrumb>
|
</sl-breadcrumb>
|
||||||
<iframe src="/dba/logs?input=%2Fapp%2F|£" allowScripts="true"
|
<iframe src="/dba/logs?input=%2Fapp%2F|£" allowScripts="true"
|
||||||
style="width:100%;height:80vh;overflow:clip;"></iframe>
|
style="width:100%;height:80vh;overflow:clip;"></iframe>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,40 +1,40 @@
|
||||||
<!DOCTYPE HTML5>
|
<!DOCTYPE HTML5>
|
||||||
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
layout:decorate="~{layout.htm}">
|
layout:decorate="~{layout.htm}">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>Dev home</title>
|
<title>Dev home</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div layout:fragment="content">
|
<div layout:fragment="content">
|
||||||
|
|
||||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a class="navbar-brand" href="#">Dev</a>
|
<a class="navbar-brand" href="#">Dev</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="navbarNav">
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
<ul class="navbar-nav">
|
<ul class="navbar-nav">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/app/dev/dba" class="nav-link" >dba</a>
|
<a href="/app/dev/dba" class="nav-link" >dba</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/app/dev/jobs" class="nav-link" >jobs</a>
|
<a href="/app/dev/jobs" class="nav-link" >jobs</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/dba/logs?input=%2Fapp%2F|£" target="_blank" class="nav-link" >DBA <sl-icon name="box-arrow-up-right"></sl-icon></a>
|
<a href="/dba/logs?input=%2Fapp%2F|£" target="_blank" class="nav-link" >DBA <sl-icon name="box-arrow-up-right"></sl-icon></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/app/api" target="_blank" class="nav-link" >wadl <sl-icon name="box-arrow-up-right"></sl-icon></a>
|
<a href="/app/api" target="_blank" class="nav-link" >wadl <sl-icon name="box-arrow-up-right"></sl-icon></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
list tasks etc
|
list tasks etc
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,28 +1,28 @@
|
||||||
<!DOCTYPE HTML5>
|
<!DOCTYPE HTML5>
|
||||||
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
layout:decorate="~{layout.htm}">
|
layout:decorate="~{layout.htm}">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>Jobs</title>
|
<title>Jobs</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div layout:fragment="content" class="container-fluid">
|
<div layout:fragment="content" class="container-fluid">
|
||||||
<div class="d-flex ">
|
<div class="d-flex ">
|
||||||
<sl-breadcrumb class="flex-grow-1" >
|
<sl-breadcrumb class="flex-grow-1" >
|
||||||
<sl-breadcrumb-item href="/app/jobs">Jobs home</sl-breadcrumb-item>
|
<sl-breadcrumb-item href="/app/jobs">Jobs home</sl-breadcrumb-item>
|
||||||
<sl-breadcrumb-item>jobs <span class="badge bg-secondary">4</span></sl-breadcrumb-item>
|
<sl-breadcrumb-item>jobs <span class="badge bg-secondary">4</span></sl-breadcrumb-item>
|
||||||
</sl-breadcrumb>
|
</sl-breadcrumb>
|
||||||
<sl-switch id="job-refresh" checked="checked" >Refresh</sl-switch>
|
<sl-switch id="job-refresh" checked="checked" >Refresh</sl-switch>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>Jobs</h2>
|
<h2>Jobs</h2>
|
||||||
<hr />
|
<hr />
|
||||||
<div hx-get="/app/jobs/table" hx-trigger="every 1s [htmx.find('#job-refresh').checked]" >
|
<div hx-get="/app/jobs/table" hx-trigger="every 1s [htmx.find('#job-refresh').checked]" >
|
||||||
Nothing Yet!
|
Nothing Yet!
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,27 +1,27 @@
|
||||||
<!DOCTYPE HTML5>
|
<!DOCTYPE HTML5>
|
||||||
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
layout:decorate="~{layout.htm}">
|
layout:decorate="~{layout.htm}">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>Error</title>
|
<title>Error</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div layout:fragment="content" class="container">
|
<div layout:fragment="content" class="container">
|
||||||
<h2 >Error: <span th:text="${code}" class="btn btn-danger"></span></h2>
|
<h2 >Error: <span th:text="${code}" class="btn btn-danger"></span></h2>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Description</dt>
|
<dt>Description</dt>
|
||||||
<dd th:text="${description}"></dd>
|
<dd th:text="${description}"></dd>
|
||||||
<dt>Value</dt>
|
<dt>Value</dt>
|
||||||
<dd th:text="${value}"></dd>
|
<dd th:text="${value}"></dd>
|
||||||
<dt>Module</dt>
|
<dt>Module</dt>
|
||||||
<dd ><span th:text="${module}"/>[<span th:text="${line-number}"/>,<span th:text="${column-number}"/>]</dd>
|
<dd ><span th:text="${module}"/>[<span th:text="${line-number}"/>,<span th:text="${column-number}"/>]</dd>
|
||||||
<dt>Additional</dt>
|
<dt>Additional</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<pre th:text="${additional}"></pre>
|
<pre th:text="${additional}"></pre>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,64 +1,64 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html layout:decorate="~{layout.htm}"
|
<html layout:decorate="~{layout.htm}"
|
||||||
xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||||
<head>
|
<head>
|
||||||
|
|
||||||
<title>Home</title>
|
<title>Home</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div layout:fragment="content" class="container">
|
<div layout:fragment="content" class="container">
|
||||||
<!-- have a button POST a click via AJAX -->
|
<!-- have a button POST a click via AJAX -->
|
||||||
<div style="display:inline-flex">
|
<div style="display:inline-flex">
|
||||||
<p th:text="${version}">ver</p>
|
<p th:text="${version}">ver</p>
|
||||||
<sl-button hx-get="http://v2.jokeapi.dev/joke/Any?format=txt&safe-mode&type=single" hx-target="#joke-container" variant="default" hx-confirm="Do you want a Joke?">
|
<sl-button hx-get="http://v2.jokeapi.dev/joke/Any?format=txt&safe-mode&type=single" hx-target="#joke-container" variant="default" hx-confirm="Do you want a Joke?">
|
||||||
<sl-icon slot="prefix" name="emoji-laughing"></sl-icon>Joke
|
<sl-icon slot="prefix" name="emoji-laughing"></sl-icon>Joke
|
||||||
</sl-button>
|
</sl-button>
|
||||||
<p id="joke-container" style="flex-grow:4"> </p>
|
<p id="joke-container" style="flex-grow:4"> </p>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<form hx-put="/pdf3/api/contact/1" hx-target="this" hx-swap="outerHTML">
|
<form hx-put="/pdf3/api/contact/1" hx-target="this" hx-swap="outerHTML">
|
||||||
<div>
|
<div>
|
||||||
<label>First Name</label>
|
<label>First Name</label>
|
||||||
<input type="text" name="firstName" value="Joe"/>
|
<input type="text" name="firstName" value="Joe"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Last Name</label>
|
<label>Last Name</label>
|
||||||
<input type="text" name="lastName" value="Blow"/>
|
<input type="text" name="lastName" value="Blow"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Email Address</label>
|
<label>Email Address</label>
|
||||||
<input type="email" name="email" value="joe@blow.com"/>
|
<input type="email" name="email" value="joe@blow.com"/>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn">Submit</button>
|
<button class="btn">Submit</button>
|
||||||
<button class="btn" hx-get="/contact/1">Cancel</button>
|
<button class="btn" hx-get="/contact/1">Cancel</button>
|
||||||
</form>
|
</form>
|
||||||
<hr />
|
<hr />
|
||||||
<h2>Contacts</h2>
|
<h2>Contacts</h2>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Email</th>
|
<th>Email</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="contacts-table" hx-get="/pdf3/api/contacts/table" hx-trigger="newContact from:body">
|
<tbody id="contacts-table" hx-get="/pdf3/api/contacts/table" hx-trigger="newContact from:body">
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<h2>Add A Contact</h2>
|
<h2>Add A Contact</h2>
|
||||||
<form hx-post="/pdf3/api/contacts">
|
<form hx-post="/pdf3/api/contacts">
|
||||||
<label>
|
<label>
|
||||||
Name
|
Name
|
||||||
<input name="name" type="text"/>
|
<input name="name" type="text"/>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
Email
|
Email
|
||||||
<input name="email" type="email"/>
|
<input name="email" type="email"/>
|
||||||
</label>
|
</label>
|
||||||
</form>
|
</form>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,68 +1,68 @@
|
||||||
<!DOCTYPE HTML5>
|
<!DOCTYPE HTML5>
|
||||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta
|
<meta
|
||||||
name="htmx-config"
|
name="htmx-config"
|
||||||
content='{
|
content='{
|
||||||
"responseHandling":[
|
"responseHandling":[
|
||||||
{"code":"204", "swap": false},
|
{"code":"204", "swap": false},
|
||||||
{"code":"[23]..", "swap": true},
|
{"code":"[23]..", "swap": true},
|
||||||
{"code":"404", "swap": true},
|
{"code":"404", "swap": true},
|
||||||
{"code":"[45]..", "swap": false, "error":true},
|
{"code":"[45]..", "swap": false, "error":true},
|
||||||
{"code":"...", "swap": true}
|
{"code":"...", "swap": true}
|
||||||
],
|
],
|
||||||
"selfRequestsOnly": false
|
"selfRequestsOnly": false
|
||||||
}'
|
}'
|
||||||
/>
|
/>
|
||||||
<title>LSP manager</title>
|
<title>LSP manager</title>
|
||||||
<link rel="icon" href="/app/static/favicon.png" />
|
<link rel="icon" href="/app/static/favicon.png" />
|
||||||
<link rel="stylesheet" href="https://unpkg.com/missing.css@1.2.0" />
|
<link rel="stylesheet" href="https://unpkg.com/missing.css@1.2.0" />
|
||||||
<link rel="stylesheet" href="/app/static/styles.css" />
|
<link rel="stylesheet" href="/app/static/styles.css" />
|
||||||
<script defer="defer" src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
<script defer="defer" src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js" integrity="sha384-yWakaGAFicqusuwOYEmoRjLNOC+6OFsdmwC2lbGQaRELtuVEqNzt11c2J711DeCZ" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js" integrity="sha384-yWakaGAFicqusuwOYEmoRjLNOC+6OFsdmwC2lbGQaRELtuVEqNzt11c2J711DeCZ" crossorigin="anonymous"></script>
|
||||||
<script defer="defer" src="/app/static/script.js"></script>
|
<script defer="defer" src="/app/static/script.js"></script>
|
||||||
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body hx-boost="true" hx-indicator="#indicator" data-bs-theme="light" >
|
<body hx-boost="true" hx-indicator="#indicator" data-bs-theme="light" >
|
||||||
<div class='App'>
|
<div class='App'>
|
||||||
<header id="header" class="navbar">
|
<header id="header" class="navbar">
|
||||||
|
|
||||||
<nav >
|
<nav >
|
||||||
|
|
||||||
<ul role="list">
|
<ul role="list">
|
||||||
<li >
|
<li >
|
||||||
<a class="active" aria-current="page" href="/app/home">Home</a>
|
<a class="active" aria-current="page" href="/app/home">Home</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li >
|
<li >
|
||||||
<a href="/app/socket">connections </a>
|
<a href="/app/socket">connections </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
<main id="main" class="App-main">
|
<main id="main" class="App-main">
|
||||||
<p layout:fragment="content">MAIN</p>
|
<p layout:fragment="content">MAIN</p>
|
||||||
</main>
|
</main>
|
||||||
<footer id="footer">
|
<footer id="footer">
|
||||||
<button onclick="toast('Hi. '+new Date())">toast</button>
|
<button onclick="toast('Hi. '+new Date())">toast</button>
|
||||||
|
|
||||||
LoggedIn: ??
|
LoggedIn: ??
|
||||||
<button type="button" class="btn btn-primary" id="liveToastBtn">Show live toast</button>
|
<button type="button" class="btn btn-primary" id="liveToastBtn">Show live toast</button>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
<!DOCTYPE HTML5>
|
<!DOCTYPE HTML5>
|
||||||
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
layout:decorate="~{layout.htm}">
|
layout:decorate="~{layout.htm}">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>Login</title>
|
<title>Login</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div layout:fragment="content">
|
<div layout:fragment="content">
|
||||||
<form onsubmit="${login}" action="${router.guardUrl()}">
|
<form onsubmit="${login}" action="${router.guardUrl()}">
|
||||||
<fieldset style="width:50%;">
|
<fieldset style="width:50%;">
|
||||||
<sl-input label="User name" value="${session.login}" oninput="${html.set(session, 'login')}"
|
<sl-input label="User name" value="${session.login}" oninput="${html.set(session, 'login')}"
|
||||||
clearable="clearable"></sl-input>
|
clearable="clearable"></sl-input>
|
||||||
|
|
||||||
<sl-input value="${session.password}" oninput="${html.set(session, 'password')}" type="password"
|
<sl-input value="${session.password}" oninput="${html.set(session, 'password')}" type="password"
|
||||||
label="Password" password-toggle="password-toggle" clearable="clearable"></sl-input>
|
label="Password" password-toggle="password-toggle" clearable="clearable"></sl-input>
|
||||||
<input type="checkbox" checked="${session.loggedIn}" />
|
<input type="checkbox" checked="${session.loggedIn}" />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<button type="submit">Login</button>
|
<button type="submit">Login</button>
|
||||||
<button onclick="${fastlogin}">Fast</button>
|
<button onclick="${fastlogin}">Fast</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,42 +1,42 @@
|
||||||
<!DOCTYPE HTML5>
|
<!DOCTYPE HTML5>
|
||||||
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
layout:decorate="~{layout.htm}">
|
layout:decorate="~{layout.htm}">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>test</title>
|
<title>test</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div layout:fragment="content">
|
<div layout:fragment="content">
|
||||||
<sl-card class="card-overview">
|
<sl-card class="card-overview">
|
||||||
|
|
||||||
<div slot="header">
|
<div slot="header">
|
||||||
<sl-tooltip>
|
<sl-tooltip>
|
||||||
<div th:text="${pdf.slug}" slot="content">path</div>
|
<div th:text="${pdf.slug}" slot="content">path</div>
|
||||||
<sl-badge th:text="${pdf.index}">{pdf.index}</sl-badge>
|
<sl-badge th:text="${pdf.index}">{pdf.index}</sl-badge>
|
||||||
</sl-tooltip>
|
</sl-tooltip>
|
||||||
|
|
||||||
<a th:href="@{/pdfs/{pdf.id}/raw}" href="/app/pdfs/{pdf.id}/details"><small>{pdf}</small></a>
|
<a th:href="@{/pdfs/{pdf.id}/raw}" href="/app/pdfs/{pdf.id}/details"><small>{pdf}</small></a>
|
||||||
<sl-button-group label="History">
|
<sl-button-group label="History">
|
||||||
<sl-icon-button name="file-earmark-pdf" label="Settings"
|
<sl-icon-button name="file-earmark-pdf" label="Settings"
|
||||||
th:href="@{/pdfs/{pdf.id}/raw}" href="/app/pdfs/{pdf.id}/view"></sl-icon-button>
|
th:href="@{/pdfs/{pdf.id}/raw}" href="/app/pdfs/{pdf.id}/view"></sl-icon-button>
|
||||||
|
|
||||||
</sl-button-group>
|
</sl-button-group>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display:flex;">
|
<div style="display:flex;">
|
||||||
<div>
|
<div>
|
||||||
<a href="/app/pdfs/{pdf.id}/details" class="holder center">
|
<a href="/app/pdfs/{pdf.id}/details" class="holder center">
|
||||||
<img src="/app/pdfs/{pdf.id}/cover" loading="{index >10?'lazy':'eager'}"
|
<img src="/app/pdfs/{pdf.id}/cover" loading="{index >10?'lazy':'eager'}"
|
||||||
alt="A kitten sits patiently." />
|
alt="A kitten sits patiently." />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
slug:<br /><small th:text="${pdf.id}">{pdf.id}</small><br />
|
slug:<br /><small th:text="${pdf.id}">{pdf.id}</small><br />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</sl-card>
|
</sl-card>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
<!DOCTYPE HTML5>
|
<!DOCTYPE HTML5>
|
||||||
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
layout:decorate="~{layout.htm}">
|
layout:decorate="~{layout.htm}">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>404</title>
|
<title>404</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div layout:fragment="content">
|
<div layout:fragment="content">
|
||||||
<h2>Page not found:</h2>
|
<h2>Page not found:</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li th:text="${path}">Page: pdf2/${ path }</li>
|
<li th:text="${path}">Page: pdf2/${ path }</li>
|
||||||
<li>Method: ${ method }</li>
|
<li>Method: ${ method }</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,28 +1,28 @@
|
||||||
{
|
{
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"textDocumentSync": 2,
|
"textDocumentSync": 2,
|
||||||
"completionProvider": {
|
"completionProvider": {
|
||||||
"resolveProvider": false,
|
"resolveProvider": false,
|
||||||
"triggerCharacters": [
|
"triggerCharacters": [
|
||||||
"\"",
|
"\"",
|
||||||
":"
|
":"
|
||||||
],
|
],
|
||||||
"documentSelector": [
|
"documentSelector": [
|
||||||
{
|
{
|
||||||
"language": "xquery"
|
"language": "xquery"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hoverProvider": true,
|
"hoverProvider": true,
|
||||||
"documentSymbolProvider": true,
|
"documentSymbolProvider": true,
|
||||||
"documentRangeFormattingProvider": false,
|
"documentRangeFormattingProvider": false,
|
||||||
"colorProvider": false,
|
"colorProvider": false,
|
||||||
"foldingRangeProvider": false,
|
"foldingRangeProvider": false,
|
||||||
"selectionRangeProvider": false,
|
"selectionRangeProvider": false,
|
||||||
"documentLinkProvider": {},
|
"documentLinkProvider": {},
|
||||||
"serverInfo": {
|
"serverInfo": {
|
||||||
"name": "XQuery 4.0b Language Server",
|
"name": "XQuery 4.0b Language Server",
|
||||||
"version": "0.0.2"
|
"version": "0.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"tabSize": 2,
|
"tabSize": 2,
|
||||||
"insertSpaces": true,
|
"insertSpaces": true,
|
||||||
"trimTrailingWhitespace": true,
|
"trimTrailingWhitespace": true,
|
||||||
"insertFinalNewline": true,
|
"insertFinalNewline": true,
|
||||||
"trimFinalNewlines": true
|
"trimFinalNewlines": true
|
||||||
}
|
}
|
||||||
|
|
@ -1,266 +1,266 @@
|
||||||
{
|
{
|
||||||
"new library module": {
|
"new library module": {
|
||||||
"isFileTemplate": true,
|
"isFileTemplate": true,
|
||||||
"prefix": "library module",
|
"prefix": "library module",
|
||||||
"body": [
|
"body": [
|
||||||
"xquery version '3.1';",
|
"xquery version '3.1';",
|
||||||
"(:~",
|
"(:~",
|
||||||
"@author: ",
|
"@author: ",
|
||||||
"@date: $CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE",
|
"@date: $CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE",
|
||||||
":)",
|
":)",
|
||||||
"module namespace ${1:prefix} = '${2:http://www.example.com/}';",
|
"module namespace ${1:prefix} = '${2:http://www.example.com/}';",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "New library module template"
|
"description": "New library module template"
|
||||||
},
|
},
|
||||||
"new main module": {
|
"new main module": {
|
||||||
"isFileTemplate": true,
|
"isFileTemplate": true,
|
||||||
"prefix": "main module",
|
"prefix": "main module",
|
||||||
"body": [
|
"body": [
|
||||||
"xquery version '3.1';",
|
"xquery version '3.1';",
|
||||||
"(:~",
|
"(:~",
|
||||||
":)",
|
":)",
|
||||||
"${1:expr}",
|
"${1:expr}",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "New main module template"
|
"description": "New main module template"
|
||||||
},
|
},
|
||||||
"flowr": {
|
"flowr": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"for",
|
"for",
|
||||||
"flowr"
|
"flowr"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"for \\$${1:var} at \\$${2:pos} in ${3:expr}",
|
"for \\$${1:var} at \\$${2:pos} in ${3:expr}",
|
||||||
"let \\$${4:var2} := ${5:expr}",
|
"let \\$${4:var2} := ${5:expr}",
|
||||||
"where ${6:boolean}",
|
"where ${6:boolean}",
|
||||||
"order by ${7:expr}",
|
"order by ${7:expr}",
|
||||||
"return ${8:expr2}"
|
"return ${8:expr2}"
|
||||||
],
|
],
|
||||||
"description": "Full FLOWR expression"
|
"description": "Full FLOWR expression"
|
||||||
},
|
},
|
||||||
"return": {
|
"return": {
|
||||||
"prefix": "return",
|
"prefix": "return",
|
||||||
"body": "return ${1:expr}"
|
"body": "return ${1:expr}"
|
||||||
},
|
},
|
||||||
"import": {
|
"import": {
|
||||||
"prefix": "import",
|
"prefix": "import",
|
||||||
"body": "import module namespace ${1:ns} = '${2:http://www.example.com/}';",
|
"body": "import module namespace ${1:ns} = '${2:http://www.example.com/}';",
|
||||||
"description": "Import module"
|
"description": "Import module"
|
||||||
},
|
},
|
||||||
"if": {
|
"if": {
|
||||||
"prefix": "if",
|
"prefix": "if",
|
||||||
"body": [
|
"body": [
|
||||||
"if (${1:boolean})",
|
"if (${1:boolean})",
|
||||||
"then ${2:expr1}",
|
"then ${2:expr1}",
|
||||||
"else ${3:expr2}"
|
"else ${3:expr2}"
|
||||||
],
|
],
|
||||||
"description": "If then else expression"
|
"description": "If then else expression"
|
||||||
},
|
},
|
||||||
"module": {
|
"module": {
|
||||||
"prefix": "module",
|
"prefix": "module",
|
||||||
"body": "module namespace ${1:ns} = '${2:http://www.example.com}';"
|
"body": "module namespace ${1:ns} = '${2:http://www.example.com}';"
|
||||||
},
|
},
|
||||||
"every": {
|
"every": {
|
||||||
"prefix": "every",
|
"prefix": "every",
|
||||||
"body": "every \\$${1:varname} in ${2:expr} satisfies ${3:expr}"
|
"body": "every \\$${1:varname} in ${2:expr} satisfies ${3:expr}"
|
||||||
},
|
},
|
||||||
"some": {
|
"some": {
|
||||||
"prefix": "some",
|
"prefix": "some",
|
||||||
"body": "some \\$${1:varname} in ${2:expr} satisfies ${3:expr}"
|
"body": "some \\$${1:varname} in ${2:expr} satisfies ${3:expr}"
|
||||||
},
|
},
|
||||||
"declare namespace": {
|
"declare namespace": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"declare",
|
"declare",
|
||||||
"namespace"
|
"namespace"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"declare ${1:prefix}='${2:namespace}';",
|
"declare ${1:prefix}='${2:namespace}';",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "declare namespace"
|
"description": "declare namespace"
|
||||||
},
|
},
|
||||||
"declare base-uri": {
|
"declare base-uri": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"declare",
|
"declare",
|
||||||
"baseuri"
|
"baseuri"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"declare base-uri '${1:uriliteral}';",
|
"declare base-uri '${1:uriliteral}';",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "declare base-uri"
|
"description": "declare base-uri"
|
||||||
},
|
},
|
||||||
"declare option": {
|
"declare option": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"declare",
|
"declare",
|
||||||
"option"
|
"option"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"declare option ${1:eqname} '${2:string}';",
|
"declare option ${1:eqname} '${2:string}';",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "declare option"
|
"description": "declare option"
|
||||||
},
|
},
|
||||||
"declare function": {
|
"declare function": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"declare",
|
"declare",
|
||||||
"function"
|
"function"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"(:~ ${1:name} :)",
|
"(:~ ${1:name} :)",
|
||||||
"declare function ${2:ns}:${1:name}()",
|
"declare function ${2:ns}:${1:name}()",
|
||||||
"as ${3:type}{",
|
"as ${3:type}{",
|
||||||
"${3:expr}",
|
"${3:expr}",
|
||||||
"};",
|
"};",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "declare function"
|
"description": "declare function"
|
||||||
},
|
},
|
||||||
"declare variable": {
|
"declare variable": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"declare",
|
"declare",
|
||||||
"variable"
|
"variable"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"(:~ \\$${1:varname} :)",
|
"(:~ \\$${1:varname} :)",
|
||||||
"declare variable \\$${1:varname} := ${2:expr};",
|
"declare variable \\$${1:varname} := ${2:expr};",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "declare variable"
|
"description": "declare variable"
|
||||||
},
|
},
|
||||||
"switch": {
|
"switch": {
|
||||||
"prefix": "switch",
|
"prefix": "switch",
|
||||||
"body": [
|
"body": [
|
||||||
"switch(${1:foo})",
|
"switch(${1:foo})",
|
||||||
"case ${2:foo} return ${3:true}",
|
"case ${2:foo} return ${3:true}",
|
||||||
"default return ${4:false}"
|
"default return ${4:false}"
|
||||||
],
|
],
|
||||||
"description": "switch statement"
|
"description": "switch statement"
|
||||||
},
|
},
|
||||||
"typeswitch": {
|
"typeswitch": {
|
||||||
"prefix": "type",
|
"prefix": "type",
|
||||||
"body": [
|
"body": [
|
||||||
"typeswitch(${1:foo})",
|
"typeswitch(${1:foo})",
|
||||||
"case ${2:foo} return ${3:true}",
|
"case ${2:foo} return ${3:true}",
|
||||||
"default return ${4:false}"
|
"default return ${4:false}"
|
||||||
],
|
],
|
||||||
"description": "typeswitch statement"
|
"description": "typeswitch statement"
|
||||||
},
|
},
|
||||||
"try": {
|
"try": {
|
||||||
"prefix": "try",
|
"prefix": "try",
|
||||||
"body": [
|
"body": [
|
||||||
"try {",
|
"try {",
|
||||||
" ${1:expr}",
|
" ${1:expr}",
|
||||||
"} catch ${2:*}",
|
"} catch ${2:*}",
|
||||||
" { ${3:expr}",
|
" { ${3:expr}",
|
||||||
"}"
|
"}"
|
||||||
],
|
],
|
||||||
"description": "try catch"
|
"description": "try catch"
|
||||||
},
|
},
|
||||||
"tumbling": {
|
"tumbling": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"for",
|
"for",
|
||||||
"tumbling",
|
"tumbling",
|
||||||
"window"
|
"window"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"for tumbling window \\$${1:varname} in ${2:expr}",
|
"for tumbling window \\$${1:varname} in ${2:expr}",
|
||||||
"start at \\$${3:start} when ${4:expr}",
|
"start at \\$${3:start} when ${4:expr}",
|
||||||
"end at \\$${5:end} when ${6:expr}",
|
"end at \\$${5:end} when ${6:expr}",
|
||||||
"return ${7:expr}"
|
"return ${7:expr}"
|
||||||
],
|
],
|
||||||
"description": "tumbling window"
|
"description": "tumbling window"
|
||||||
},
|
},
|
||||||
"sliding": {
|
"sliding": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"for",
|
"for",
|
||||||
"sliding",
|
"sliding",
|
||||||
"window"
|
"window"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"for sliding window \\$${1:varname} in ${2:expr}",
|
"for sliding window \\$${1:varname} in ${2:expr}",
|
||||||
"start at \\$${3:start} when ${4:expr}",
|
"start at \\$${3:start} when ${4:expr}",
|
||||||
"end at \\$${5:end} when ${6:expr}",
|
"end at \\$${5:end} when ${6:expr}",
|
||||||
"return ${7:expr}"
|
"return ${7:expr}"
|
||||||
],
|
],
|
||||||
"description": "sliding window"
|
"description": "sliding window"
|
||||||
},
|
},
|
||||||
"let": {
|
"let": {
|
||||||
"prefix": "let",
|
"prefix": "let",
|
||||||
"body": "let \\$${1:varname} := ${2:expr}"
|
"body": "let \\$${1:varname} := ${2:expr}"
|
||||||
},
|
},
|
||||||
"castable": {
|
"castable": {
|
||||||
"body": "castable as ${1:atomicType}"
|
"body": "castable as ${1:atomicType}"
|
||||||
},
|
},
|
||||||
"cast": {
|
"cast": {
|
||||||
"body": "cast as ${1:atomicType}"
|
"body": "cast as ${1:atomicType}"
|
||||||
},
|
},
|
||||||
|
|
||||||
"update insert": {
|
"update insert": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"update",
|
"update",
|
||||||
"insert"
|
"insert"
|
||||||
],
|
],
|
||||||
"body": "insert node ${1:expr} into ${2:xpath}"
|
"body": "insert node ${1:expr} into ${2:xpath}"
|
||||||
},
|
},
|
||||||
"update delete": {
|
"update delete": {
|
||||||
"prefix": ["delete","update"],
|
"prefix": ["delete","update"],
|
||||||
"body": "delete node ${1:xpath}"
|
"body": "delete node ${1:xpath}"
|
||||||
},
|
},
|
||||||
"update replace node": {
|
"update replace node": {
|
||||||
"prefix":["update","replace"],
|
"prefix":["update","replace"],
|
||||||
"body": "replace node ${1:xpath} with ${2:expr}"
|
"body": "replace node ${1:xpath} with ${2:expr}"
|
||||||
},
|
},
|
||||||
"update replace value": {
|
"update replace value": {
|
||||||
"prefix": [ "update",
|
"prefix": [ "update",
|
||||||
"replace",
|
"replace",
|
||||||
"value"
|
"value"
|
||||||
],
|
],
|
||||||
"body": "replace value of node ${1:xpath} with ${2:expr}"
|
"body": "replace value of node ${1:xpath} with ${2:expr}"
|
||||||
},
|
},
|
||||||
"update rename": {
|
"update rename": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"update",
|
"update",
|
||||||
"rename"
|
"rename"
|
||||||
],
|
],
|
||||||
"body": "rename node ${1:xpath} as ${2:eqname}"
|
"body": "rename node ${1:xpath} as ${2:eqname}"
|
||||||
},
|
},
|
||||||
"copy modify return": {
|
"copy modify return": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"copy",
|
"copy",
|
||||||
"modify",
|
"modify",
|
||||||
"return"
|
"return"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"copy \\$${1:varname} := ${2:node}",
|
"copy \\$${1:varname} := ${2:node}",
|
||||||
"modify ${3:updates}",
|
"modify ${3:updates}",
|
||||||
"return \\$${1:varname}"
|
"return \\$${1:varname}"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"transform with": {
|
"transform with": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"transform",
|
"transform",
|
||||||
"with",
|
"with",
|
||||||
"update"
|
"update"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"${1:node} transform with {",
|
"${1:node} transform with {",
|
||||||
" ${2:update}",
|
" ${2:update}",
|
||||||
"}"
|
"}"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"transform update": {
|
"transform update": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"transform",
|
"transform",
|
||||||
"update"
|
"update"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"${1:node} update {",
|
"${1:node} update {",
|
||||||
"${2:update}",
|
"${2:update}",
|
||||||
"}"
|
"}"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,279 +1,279 @@
|
||||||
{
|
{
|
||||||
"new library module": {
|
"new library module": {
|
||||||
"isFileTemplate": true,
|
"isFileTemplate": true,
|
||||||
"prefix": "library module",
|
"prefix": "library module",
|
||||||
"body": [
|
"body": [
|
||||||
"xquery version '3.1';",
|
"xquery version '3.1';",
|
||||||
"(:~",
|
"(:~",
|
||||||
"@author: ",
|
"@author: ",
|
||||||
"@date: $CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE",
|
"@date: $CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE",
|
||||||
":)",
|
":)",
|
||||||
"module namespace ${1:prefix} = '${2:http://www.example.com/}';",
|
"module namespace ${1:prefix} = '${2:http://www.example.com/}';",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "New library module template"
|
"description": "New library module template"
|
||||||
},
|
},
|
||||||
"new main module": {
|
"new main module": {
|
||||||
"isFileTemplate": true,
|
"isFileTemplate": true,
|
||||||
"prefix": "main module",
|
"prefix": "main module",
|
||||||
"body": [
|
"body": [
|
||||||
"xquery version '3.1';",
|
"xquery version '3.1';",
|
||||||
"(:~",
|
"(:~",
|
||||||
":)",
|
":)",
|
||||||
"${1:expr}",
|
"${1:expr}",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "New main module template"
|
"description": "New main module template"
|
||||||
},
|
},
|
||||||
"flowr": {
|
"flowr": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"for",
|
"for",
|
||||||
"flowr"
|
"flowr"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"for \\$${1:var} at \\$${2:pos} in ${3:expr}",
|
"for \\$${1:var} at \\$${2:pos} in ${3:expr}",
|
||||||
"let \\$${4:var2} := ${5:expr}",
|
"let \\$${4:var2} := ${5:expr}",
|
||||||
"where ${6:boolean}",
|
"where ${6:boolean}",
|
||||||
"order by ${7:expr}",
|
"order by ${7:expr}",
|
||||||
"return ${8:expr2}"
|
"return ${8:expr2}"
|
||||||
],
|
],
|
||||||
"description": "Full FLOWR expression"
|
"description": "Full FLOWR expression"
|
||||||
},
|
},
|
||||||
"return": {
|
"return": {
|
||||||
"prefix": "return",
|
"prefix": "return",
|
||||||
"body": "return ${1:expr}"
|
"body": "return ${1:expr}"
|
||||||
},
|
},
|
||||||
"import": {
|
"import": {
|
||||||
"prefix": "import",
|
"prefix": "import",
|
||||||
"body": "import module namespace ${1:ns} = '${2:http://www.example.com/}';",
|
"body": "import module namespace ${1:ns} = '${2:http://www.example.com/}';",
|
||||||
"description": "Import module"
|
"description": "Import module"
|
||||||
},
|
},
|
||||||
"if": {
|
"if": {
|
||||||
"prefix": "if",
|
"prefix": "if",
|
||||||
"body": [
|
"body": [
|
||||||
"if (${1:boolean})",
|
"if (${1:boolean})",
|
||||||
"then ${2:expr1}",
|
"then ${2:expr1}",
|
||||||
"else ${3:expr2}"
|
"else ${3:expr2}"
|
||||||
],
|
],
|
||||||
"description": "If then else expression"
|
"description": "If then else expression"
|
||||||
},
|
},
|
||||||
"module": {
|
"module": {
|
||||||
"prefix": "module",
|
"prefix": "module",
|
||||||
"body": "module namespace ${1:ns} = '${2:http://www.example.com}';"
|
"body": "module namespace ${1:ns} = '${2:http://www.example.com}';"
|
||||||
},
|
},
|
||||||
"every": {
|
"every": {
|
||||||
"prefix": "every",
|
"prefix": "every",
|
||||||
"body": "every \\$${1:varname} in ${2:expr} satisfies ${3:expr}"
|
"body": "every \\$${1:varname} in ${2:expr} satisfies ${3:expr}"
|
||||||
},
|
},
|
||||||
"some": {
|
"some": {
|
||||||
"prefix": "some",
|
"prefix": "some",
|
||||||
"body": "some \\$${1:varname} in ${2:expr} satisfies ${3:expr}"
|
"body": "some \\$${1:varname} in ${2:expr} satisfies ${3:expr}"
|
||||||
},
|
},
|
||||||
"declare namespace": {
|
"declare namespace": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"declare",
|
"declare",
|
||||||
"namespace"
|
"namespace"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"declare ${1:prefix}='${2:namespace}';",
|
"declare ${1:prefix}='${2:namespace}';",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "declare namespace"
|
"description": "declare namespace"
|
||||||
},
|
},
|
||||||
"declare base-uri": {
|
"declare base-uri": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"declare",
|
"declare",
|
||||||
"baseuri"
|
"baseuri"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"declare base-uri '${1:uriliteral}';",
|
"declare base-uri '${1:uriliteral}';",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "declare base-uri"
|
"description": "declare base-uri"
|
||||||
},
|
},
|
||||||
"declare option": {
|
"declare option": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"declare",
|
"declare",
|
||||||
"option"
|
"option"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"declare option ${1:eqname} '${2:string}';",
|
"declare option ${1:eqname} '${2:string}';",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "declare option"
|
"description": "declare option"
|
||||||
},
|
},
|
||||||
"declare function": {
|
"declare function": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"declare",
|
"declare",
|
||||||
"function"
|
"function"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"(:~ ${1:name} :)",
|
"(:~ ${1:name} :)",
|
||||||
"declare function ${2:ns}:${1:name}()",
|
"declare function ${2:ns}:${1:name}()",
|
||||||
"as ${3:type}{",
|
"as ${3:type}{",
|
||||||
"${3:expr}",
|
"${3:expr}",
|
||||||
"};",
|
"};",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "declare function"
|
"description": "declare function"
|
||||||
},
|
},
|
||||||
"declare variable": {
|
"declare variable": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"declare",
|
"declare",
|
||||||
"variable"
|
"variable"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"(:~ \\$${1:varname} :)",
|
"(:~ \\$${1:varname} :)",
|
||||||
"declare variable \\$${1:varname} := ${2:expr};",
|
"declare variable \\$${1:varname} := ${2:expr};",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
"description": "declare variable"
|
"description": "declare variable"
|
||||||
},
|
},
|
||||||
"switch": {
|
"switch": {
|
||||||
"prefix": "switch",
|
"prefix": "switch",
|
||||||
"body": [
|
"body": [
|
||||||
"switch(${1:foo})",
|
"switch(${1:foo})",
|
||||||
"case ${2:foo} return ${3:true}",
|
"case ${2:foo} return ${3:true}",
|
||||||
"default return ${4:false}"
|
"default return ${4:false}"
|
||||||
],
|
],
|
||||||
"description": "switch statement"
|
"description": "switch statement"
|
||||||
},
|
},
|
||||||
"typeswitch": {
|
"typeswitch": {
|
||||||
"prefix": "type",
|
"prefix": "type",
|
||||||
"body": [
|
"body": [
|
||||||
"typeswitch(${1:foo})",
|
"typeswitch(${1:foo})",
|
||||||
"case ${2:foo} return ${3:true}",
|
"case ${2:foo} return ${3:true}",
|
||||||
"default return ${4:false}"
|
"default return ${4:false}"
|
||||||
],
|
],
|
||||||
"description": "typeswitch statement"
|
"description": "typeswitch statement"
|
||||||
},
|
},
|
||||||
"try": {
|
"try": {
|
||||||
"prefix": "try",
|
"prefix": "try",
|
||||||
"body": [
|
"body": [
|
||||||
"try {",
|
"try {",
|
||||||
" ${1:expr}",
|
" ${1:expr}",
|
||||||
"} catch ${2:*}",
|
"} catch ${2:*}",
|
||||||
" { ${3:expr}",
|
" { ${3:expr}",
|
||||||
"}"
|
"}"
|
||||||
],
|
],
|
||||||
"description": "try catch"
|
"description": "try catch"
|
||||||
},
|
},
|
||||||
"tumbling": {
|
"tumbling": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"for",
|
"for",
|
||||||
"tumbling",
|
"tumbling",
|
||||||
"window"
|
"window"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"for tumbling window \\$${1:varname} in ${2:expr}",
|
"for tumbling window \\$${1:varname} in ${2:expr}",
|
||||||
"start at \\$${3:start} when ${4:expr}",
|
"start at \\$${3:start} when ${4:expr}",
|
||||||
"end at \\$${5:end} when ${6:expr}",
|
"end at \\$${5:end} when ${6:expr}",
|
||||||
"return ${7:expr}"
|
"return ${7:expr}"
|
||||||
],
|
],
|
||||||
"description": "tumbling window"
|
"description": "tumbling window"
|
||||||
},
|
},
|
||||||
"sliding": {
|
"sliding": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"for",
|
"for",
|
||||||
"sliding",
|
"sliding",
|
||||||
"window"
|
"window"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"for sliding window \\$${1:varname} in ${2:expr}",
|
"for sliding window \\$${1:varname} in ${2:expr}",
|
||||||
"start at \\$${3:start} when ${4:expr}",
|
"start at \\$${3:start} when ${4:expr}",
|
||||||
"end at \\$${5:end} when ${6:expr}",
|
"end at \\$${5:end} when ${6:expr}",
|
||||||
"return ${7:expr}"
|
"return ${7:expr}"
|
||||||
],
|
],
|
||||||
"description": "sliding window"
|
"description": "sliding window"
|
||||||
},
|
},
|
||||||
"let": {
|
"let": {
|
||||||
"prefix": "let",
|
"prefix": "let",
|
||||||
"body": "let \\$${1:varname} := ${2:expr}"
|
"body": "let \\$${1:varname} := ${2:expr}"
|
||||||
},
|
},
|
||||||
"castable": {
|
"castable": {
|
||||||
"body": "castable as ${1:atomicType}"
|
"body": "castable as ${1:atomicType}"
|
||||||
},
|
},
|
||||||
"cast": {
|
"cast": {
|
||||||
"body": "cast as ${1:atomicType}"
|
"body": "cast as ${1:atomicType}"
|
||||||
},
|
},
|
||||||
// Updates ***************
|
// Updates ***************
|
||||||
"update insert": {
|
"update insert": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"update",
|
"update",
|
||||||
"insert"
|
"insert"
|
||||||
],
|
],
|
||||||
"body": "insert node ${1:expr} into ${2:xpath}"
|
"body": "insert node ${1:expr} into ${2:xpath}"
|
||||||
},
|
},
|
||||||
"update delete": {
|
"update delete": {
|
||||||
"prefix": ["delete","update"],
|
"prefix": ["delete","update"],
|
||||||
"body": "delete node ${1:xpath}"
|
"body": "delete node ${1:xpath}"
|
||||||
},
|
},
|
||||||
"update replace node": {
|
"update replace node": {
|
||||||
"prefix":["update","replace"],
|
"prefix":["update","replace"],
|
||||||
"body": "replace node ${1:xpath} with ${2:expr}"
|
"body": "replace node ${1:xpath} with ${2:expr}"
|
||||||
},
|
},
|
||||||
"update replace value": {
|
"update replace value": {
|
||||||
"prefix": [ "update",
|
"prefix": [ "update",
|
||||||
"replace",
|
"replace",
|
||||||
"value"
|
"value"
|
||||||
],
|
],
|
||||||
"body": "replace value of node ${1:xpath} with ${2:expr}"
|
"body": "replace value of node ${1:xpath} with ${2:expr}"
|
||||||
},
|
},
|
||||||
"update rename": {
|
"update rename": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"update",
|
"update",
|
||||||
"rename"
|
"rename"
|
||||||
],
|
],
|
||||||
"body": "rename node ${1:xpath} as ${2:eqname}"
|
"body": "rename node ${1:xpath} as ${2:eqname}"
|
||||||
},
|
},
|
||||||
"copy modify return": {
|
"copy modify return": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"copy",
|
"copy",
|
||||||
"modify",
|
"modify",
|
||||||
"return"
|
"return"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"copy \\$${1:varname} := ${2:node}",
|
"copy \\$${1:varname} := ${2:node}",
|
||||||
"modify ${3:updates}",
|
"modify ${3:updates}",
|
||||||
"return \\$${1:varname}"
|
"return \\$${1:varname}"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"transform with": {
|
"transform with": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"transform",
|
"transform",
|
||||||
"with",
|
"with",
|
||||||
"update"
|
"update"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"${1:node} transform with {",
|
"${1:node} transform with {",
|
||||||
" ${2:update}",
|
" ${2:update}",
|
||||||
"}"
|
"}"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"transform update": {
|
"transform update": {
|
||||||
"prefix": [
|
"prefix": [
|
||||||
"transform",
|
"transform",
|
||||||
"update"
|
"update"
|
||||||
],
|
],
|
||||||
"body": [
|
"body": [
|
||||||
"${1:node} update {",
|
"${1:node} update {",
|
||||||
"${2:update}",
|
"${2:update}",
|
||||||
"}"
|
"}"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//snippet group
|
//snippet group
|
||||||
// group by $${1:varname} := ${2:expr}
|
// group by $${1:varname} := ${2:expr}
|
||||||
//snippet order
|
//snippet order
|
||||||
// order by ${1:expr} ${2:descending}
|
// order by ${1:expr} ${2:descending}
|
||||||
//snippet stable
|
//snippet stable
|
||||||
// stable order by ${1:expr}
|
// stable order by ${1:expr}
|
||||||
//snippet count
|
//snippet count
|
||||||
// count $${1:varname}
|
// count $${1:varname}
|
||||||
//snippet ordered
|
//snippet ordered
|
||||||
// ordered { ${1:expr} }
|
// ordered { ${1:expr} }
|
||||||
//snippet unordered
|
//snippet unordered
|
||||||
// unordered { ${1:expr} }
|
// unordered { ${1:expr} }
|
||||||
//snippet treat
|
//snippet treat
|
||||||
// treat as ${1:expr}
|
// treat as ${1:expr}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
module namespace lint="lsp/lint";
|
module namespace lint="lsp/lint";
|
||||||
(:
|
(:
|
||||||
Describes a problem or hint for a piece of code.
|
Describes a problem or hint for a piece of code.
|
||||||
|
|
||||||
from: number The start position of the relevant text.
|
from: number The start position of the relevant text.
|
||||||
to: number The end position. May be equal to from, though actually covering text is preferable.
|
to: number The end position. May be equal to from, though actually covering text is preferable.
|
||||||
severity: "error" | "hint" | "info" | "warning". The severity of the problem. This will influence how it is displayed.
|
severity: "error" | "hint" | "info" | "warning". The severity of the problem. This will influence how it is displayed.
|
||||||
|
|
||||||
markClass?: string When given, add an extra CSS class to parts of the code that this diagnostic applies to.
|
markClass?: string When given, add an extra CSS class to parts of the code that this diagnostic applies to.
|
||||||
|
|
||||||
source?: string An optional source string indicating where the diagnostic is coming from. You can put the name of your linter here, if applicable.
|
source?: string An optional source string indicating where the diagnostic is coming from. You can put the name of your linter here, if applicable.
|
||||||
|
|
||||||
message: string The message associated with this diagnostic.
|
message: string The message associated with this diagnostic.
|
||||||
|
|
||||||
renderMessage?: fn(view: EditorView) → Node An optional custom rendering function that displays the message as a DOM node.
|
renderMessage?: fn(view: EditorView) → Node An optional custom rendering function that displays the message as a DOM node.
|
||||||
|
|
||||||
actions?: readonly Action[] An optional array of actions that can be taken on this diagnostic.
|
actions?: readonly Action[] An optional array of actions that can be taken on this diagnostic.
|
||||||
:)
|
:)
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
job:eval(xs:anyURI("parse.xq"),
|
job:eval(xs:anyURI("parse.xq"),
|
||||||
{"textDocument":"2+3","webSocket":ws:id()},
|
{"textDocument":"2+3","webSocket":ws:id()},
|
||||||
{ 'cache': true() }
|
{ 'cache': true() }
|
||||||
)
|
)
|
||||||
|
|
@ -1,28 +1,28 @@
|
||||||
import * as aceBuilds from 'https://esm.run/ace-builds';
|
import * as aceBuilds from 'https://esm.run/ace-builds';
|
||||||
|
|
||||||
import ace from 'https://cdn.jsdelivr.net/npm/ace/+esm'
|
import ace from 'https://cdn.jsdelivr.net/npm/ace/+esm'
|
||||||
|
|
||||||
/* import 'ace-builds/src-noconflict/mode-javascript';
|
/* import 'ace-builds/src-noconflict/mode-javascript';
|
||||||
import 'ace-builds/src-noconflict/theme-chrome'; */
|
import 'ace-builds/src-noconflict/theme-chrome'; */
|
||||||
|
|
||||||
/* import {AceLanguageClient} from "ace-linters/build/ace-language-client";
|
/* import {AceLanguageClient} from "ace-linters/build/ace-language-client";
|
||||||
|
|
||||||
const serverData = {
|
const serverData = {
|
||||||
module: () => import("ace-linters/build/language-client"),
|
module: () => import("ace-linters/build/language-client"),
|
||||||
modes: "json|json5",
|
modes: "json|json5",
|
||||||
type: "socket",
|
type: "socket",
|
||||||
socket: new WebSocket("ws://127.0.0.1:3000/ws/lsp"), // your websocket server address
|
socket: new WebSocket("ws://127.0.0.1:3000/ws/lsp"), // your websocket server address
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// Initialize the editor
|
// Initialize the editor
|
||||||
const editor = ace.edit("editor", {
|
const editor = ace.edit("editor", {
|
||||||
theme: "ace/theme/chrome",
|
theme: "ace/theme/chrome",
|
||||||
mode: "ace/mode/javascript",
|
mode: "ace/mode/javascript",
|
||||||
fontSize: "14px",
|
fontSize: "14px",
|
||||||
showPrintMargin: false,
|
showPrintMargin: false,
|
||||||
useWorker: false // Disable web worker for this simple demo
|
useWorker: false // Disable web worker for this simple demo
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a language provider for WebSocket
|
// Create a language provider for WebSocket
|
||||||
//let languageProvider = AceLanguageClient.for(serverData);
|
//let languageProvider = AceLanguageClient.for(serverData);
|
||||||
//languageProvider.registerEditor(editor);
|
//languageProvider.registerEditor(editor);
|
||||||
|
|
@ -1,52 +1,52 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en-US">
|
<html lang="en-US">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>BaseX LSP</title>
|
<title>BaseX LSP</title>
|
||||||
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ace.js"></script>
|
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ace.js"></script>
|
||||||
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ext-language_tools.js"></script>
|
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ext-language_tools.js"></script>
|
||||||
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ext-modelist.js"></script>
|
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ext-modelist.js"></script>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<script src="https://www.unpkg.com/ace-linters@latest/build/ace-linters.js"></script>
|
<script src="https://www.unpkg.com/ace-linters@latest/build/ace-linters.js"></script>
|
||||||
<script src="https://www.unpkg.com/ace-linters@latest/build/ace-language-client.js"></script>
|
<script src="https://www.unpkg.com/ace-linters@latest/build/ace-language-client.js"></script>
|
||||||
<script type="module" src="acego.js"></script>
|
<script type="module" src="acego.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div>something<button onclick="foo()">send</button><a href="/dba/logs" target="_blank">dba</a></div>
|
<div>something<button onclick="foo()">send</button><a href="/dba/logs" target="_blank">dba</a></div>
|
||||||
<div id="editor" style="height: 100px">some text</div>
|
<div id="editor" style="height: 100px">some text</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var modelist = ace.require('ace/ext/modelist');
|
var modelist = ace.require('ace/ext/modelist');
|
||||||
if(modelist.modesByName['json'] == undefined) {
|
if(modelist.modesByName['json'] == undefined) {
|
||||||
console.log("mode doesn't exist");
|
console.log("mode doesn't exist");
|
||||||
}
|
}
|
||||||
var servers = [
|
var servers = [
|
||||||
{
|
{
|
||||||
module: () => import("XXXXXace-linters/build/language-client"),
|
module: () => import("XXXXXace-linters/build/language-client"),
|
||||||
modes: "json",
|
modes: "json",
|
||||||
type: "socket",
|
type: "socket",
|
||||||
socket: new WebSocket("ws://127.0.0.1:3000/ws/lsp"),
|
socket: new WebSocket("ws://127.0.0.1:3000/ws/lsp"),
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
let languageProvider = AceLanguageClient.for(servers);
|
let languageProvider = AceLanguageClient.for(servers);
|
||||||
|
|
||||||
ace.require("ace/ext/language_tools"); //To allow autocompletion
|
ace.require("ace/ext/language_tools"); //To allow autocompletion
|
||||||
var editor = ace.edit("editor", {
|
var editor = ace.edit("editor", {
|
||||||
enableBasicAutocompletion: true,
|
enableBasicAutocompletion: true,
|
||||||
enableLiveAutocompletion: true,
|
enableLiveAutocompletion: true,
|
||||||
mode: "json"
|
mode: "json"
|
||||||
});
|
});
|
||||||
|
|
||||||
languageProvider.registerEditor(editor);
|
languageProvider.registerEditor(editor);
|
||||||
// editor.session.setMode("astro"); // mode now contains "ace/mode/javascript".
|
// editor.session.setMode("astro"); // mode now contains "ace/mode/javascript".
|
||||||
function foo(){
|
function foo(){
|
||||||
servers[0].socket.send("TTTTT")
|
servers[0].socket.send("TTTTT")
|
||||||
alert("hi")
|
alert("hi")
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,29 +1,29 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en-US">
|
<html lang="en-US">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
<meta name="viewport" content="width=device-width,height=device-height" />
|
<meta name="viewport" content="width=device-width,height=device-height" />
|
||||||
<title>BaseX LSP Demo WIP</title>
|
<title>BaseX LSP Demo WIP</title>
|
||||||
<link rel="stylesheet" href="styles.css">
|
<link rel="stylesheet" href="styles.css">
|
||||||
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ace.js"></script>
|
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ace.js"></script>
|
||||||
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ext-language_tools.js"></script>
|
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ext-language_tools.js"></script>
|
||||||
<script src="https://www.unpkg.com/ace-linters@latest/build/ace-linters.js"></script>
|
<script src="https://www.unpkg.com/ace-linters@latest/build/ace-linters.js"></script>
|
||||||
<script src="https://www.unpkg.com/ace-linters@latest/build/service-manager.js"></script>
|
<script src="https://www.unpkg.com/ace-linters@latest/build/service-manager.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<header>something
|
<header>something
|
||||||
<button onclick="opts(editor)">console</button>
|
<button onclick="opts(editor)">console</button>
|
||||||
<button onclick="editor.showSettingsMenu();">Settings</button>
|
<button onclick="editor.showSettingsMenu();">Settings</button>
|
||||||
<a href="/dba/logs" target="_blank">dba</a>
|
<a href="/dba/logs" target="_blank">dba</a>
|
||||||
</header>
|
</header>
|
||||||
<div>
|
<div>
|
||||||
<div id="settings" style="height: 100px">sett</div>
|
<div id="settings" style="height: 100px">sett</div>
|
||||||
<div id="editor" style="height: 100px">some text</div>
|
<div id="editor" style="height: 100px">some text</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="script.js"></script>
|
<script src="script.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,42 +1,42 @@
|
||||||
ace.require("ace/ext/language_tools"); //To allow autocompletion
|
ace.require("ace/ext/language_tools"); //To allow autocompletion
|
||||||
var editor = ace.edit("editor", {
|
var editor = ace.edit("editor", {
|
||||||
enableBasicAutocompletion: true,
|
enableBasicAutocompletion: true,
|
||||||
enableLiveAutocompletion: true,
|
enableLiveAutocompletion: true,
|
||||||
theme: "ace/theme/chrome",
|
theme: "ace/theme/chrome",
|
||||||
mode: "ace/mode/html",
|
mode: "ace/mode/html",
|
||||||
fontSize: "14px",
|
fontSize: "14px",
|
||||||
showPrintMargin: false,
|
showPrintMargin: false,
|
||||||
useWorker: false // Disable web worker for this simple demo
|
useWorker: false // Disable web worker for this simple demo
|
||||||
});
|
});
|
||||||
|
|
||||||
ace.require('ace/ext/settings_menu');
|
ace.require('ace/ext/settings_menu');
|
||||||
editor.setTheme("ace/theme/github");
|
editor.setTheme("ace/theme/github");
|
||||||
//editor.session.setMode("ace/mode/html");
|
//editor.session.setMode("ace/mode/html");
|
||||||
editor.commands.addCommands([
|
editor.commands.addCommands([
|
||||||
{
|
{
|
||||||
name: "showSettingsMenu",
|
name: "showSettingsMenu",
|
||||||
bindKey: {
|
bindKey: {
|
||||||
win: "Ctrl-q",
|
win: "Ctrl-q",
|
||||||
mac: "Ctrl-q"
|
mac: "Ctrl-q"
|
||||||
},
|
},
|
||||||
exec: function (editor) {
|
exec: function (editor) {
|
||||||
editor.showSettingsMenu();
|
editor.showSettingsMenu();
|
||||||
},
|
},
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
var provider = LanguageProvider.fromCdn("https://www.unpkg.com/ace-linters@latest/build/");
|
var provider = LanguageProvider.fromCdn("https://www.unpkg.com/ace-linters@latest/build/");
|
||||||
provider.registerEditor(editor);
|
provider.registerEditor(editor);
|
||||||
|
|
||||||
const serverData = {
|
const serverData = {
|
||||||
module: () => import("https://www.unpkg.com/ace-linters@latest/build/language-client"),
|
module: () => import("https://www.unpkg.com/ace-linters@latest/build/language-client"),
|
||||||
modes: "json|json5",
|
modes: "json|json5",
|
||||||
type: "socket",
|
type: "socket",
|
||||||
socket: new WebSocket("ws://127.0.0.1:3000/ws/lsp"), // your websocket server address
|
socket: new WebSocket("ws://127.0.0.1:3000/ws/lsp"), // your websocket server address
|
||||||
}
|
}
|
||||||
|
|
||||||
function opts(editor) {
|
function opts(editor) {
|
||||||
const modes=editor.session.$modes;
|
const modes=editor.session.$modes;
|
||||||
console.log(editor.session.$modeId);
|
console.log(editor.session.$modeId);
|
||||||
console.log(Object.keys(modes));
|
console.log(Object.keys(modes));
|
||||||
}
|
}
|
||||||
|
|
@ -1,33 +1,33 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en-US">
|
<html lang="en-US">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
<meta name="viewport" content="width=device-width,height=device-height" />
|
<meta name="viewport" content="width=device-width,height=device-height" />
|
||||||
<title>BaseX LSP</title>
|
<title>BaseX LSP</title>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div>Socket <button onclick="foo()">send</button><a href="/dba/logs" target="_blank">dba</a></div>
|
<div>Socket <button onclick="foo()">send</button><a href="/dba/logs" target="_blank">dba</a></div>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
var socket = new WebSocket("ws://127.0.0.1:3000/ws/lsp") // address of your websocket server
|
var socket = new WebSocket("ws://127.0.0.1:3000/ws/lsp") // address of your websocket server
|
||||||
// Listen for possible errors
|
// Listen for possible errors
|
||||||
socket.addEventListener("error", (event) => {
|
socket.addEventListener("error", (event) => {
|
||||||
console.log("WebSocket error: ", event);
|
console.log("WebSocket error: ", event);
|
||||||
});
|
});
|
||||||
socket.addEventListener("close", (event) => {
|
socket.addEventListener("close", (event) => {
|
||||||
console.log("closed", event.code, event.reason, event.wasClean);
|
console.log("closed", event.code, event.reason, event.wasClean);
|
||||||
});
|
});
|
||||||
socket.addEventListener("open", (event) => {
|
socket.addEventListener("open", (event) => {
|
||||||
setInterval(function ping() { socket.send('{"type":"ping","msg":"staying alive"}'); }, 100000);
|
setInterval(function ping() { socket.send('{"type":"ping","msg":"staying alive"}'); }, 100000);
|
||||||
socket.send('{"type":"ping","msg":"Hello Server!"}');
|
socket.send('{"type":"ping","msg":"Hello Server!"}');
|
||||||
});
|
});
|
||||||
function foo() {
|
function foo() {
|
||||||
socket.send('{"type":"ping","msg":"foo!"}');
|
socket.send('{"type":"ping","msg":"foo!"}');
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
header {
|
header {
|
||||||
background-color: aqua;
|
background-color: aqua;
|
||||||
}
|
}
|
||||||
.box {
|
.box {
|
||||||
border: 2px dotted rgb(96 139 168);
|
border: 2px dotted rgb(96 139 168);
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
@ -1,122 +1,122 @@
|
||||||
@import url("../codicon@0.0.40/codicon.css");
|
@import url("../codicon@0.0.40/codicon.css");
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
color-scheme: light dark;
|
color-scheme: light dark;
|
||||||
--quiet-primary-seed: #e98d61;
|
--quiet-primary-seed: #e98d61;
|
||||||
--quiet-content-spacing: 0.75rem;
|
--quiet-content-spacing: 0.75rem;
|
||||||
--quiet-form-control-height-md:0.9rem;
|
--quiet-form-control-height-md:0.9rem;
|
||||||
--quiet-focus-width: 2px;
|
--quiet-focus-width: 2px;
|
||||||
--quiet-focus-offset: 0px;
|
--quiet-focus-offset: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
form header {
|
form header {
|
||||||
background-color: burlywood;
|
background-color: burlywood;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-wrap {
|
.page-wrap {
|
||||||
background: white;
|
background: white;
|
||||||
height: 100vh ;
|
height: 100vh ;
|
||||||
|
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(10px, 1fr) minmax(10px, 4fr);
|
grid-template-columns: minmax(10px, 1fr) minmax(10px, 4fr);
|
||||||
grid-template-rows: min-content min-content 1fr min-content;
|
grid-template-rows: min-content min-content 1fr min-content;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
details {
|
details {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
details[open] {
|
details[open] {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
summary {
|
summary {
|
||||||
background-color: var(--quiet-neutral-fill-softer);
|
background-color: var(--quiet-neutral-fill-softer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set editor dimensions */
|
/* Set editor dimensions */
|
||||||
#editor {
|
#editor {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: 75cqh;
|
height: 75cqh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stretch editor to fit inside its containing div */
|
/* Stretch editor to fit inside its containing div */
|
||||||
.cm-editor {
|
.cm-editor {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
details[open]::details-content {
|
details[open]::details-content {
|
||||||
padding: 0.1em;
|
padding: 0.1em;
|
||||||
border: thin solid grey;
|
border: thin solid grey;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
::backdrop {
|
::backdrop {
|
||||||
backdrop-filter: blur(2px);
|
backdrop-filter: blur(2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
grid-template-columns: 100%;
|
grid-template-columns: 100%;
|
||||||
grid-template-rows: auto;
|
grid-template-rows: auto;
|
||||||
|
|
||||||
>* {
|
>* {
|
||||||
grid-column: 1 / -1 !important;
|
grid-column: 1 / -1 !important;
|
||||||
grid-row: auto !important;
|
grid-row: auto !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#tConnect:state(unchecked) {
|
#tConnect:state(unchecked) {
|
||||||
outline: dashed 4px deeppink;
|
outline: dashed 4px deeppink;
|
||||||
outline-offset: 4px;
|
outline-offset: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-header {
|
.page-header {
|
||||||
grid-column: 1 / -1;
|
grid-column: 1 / -1;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
background: #ffecb3;
|
background: #ffecb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-sidebar {
|
.page-sidebar {
|
||||||
grid-column: 1 / 2;
|
grid-column: 1 / 2;
|
||||||
grid-row: 2 / 4;
|
grid-row: 2 / 4;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
details {
|
details {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-nav {
|
.page-nav {
|
||||||
grid-column: 2 / 3;
|
grid-column: 2 / 3;
|
||||||
background: red;
|
background: red;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-main {
|
.page-main {
|
||||||
grid-column: 2 / 3;
|
grid-column: 2 / 3;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-footer {
|
.page-footer {
|
||||||
grid-column: 1 / -1;
|
grid-column: 1 / -1;
|
||||||
background: #ffecb3;
|
background: #ffecb3;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding:2px;
|
padding:2px;
|
||||||
}
|
}
|
||||||
|
|
@ -1,307 +1,307 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en" class="quiet-cloak quiet-blue"
|
<html lang="en" class="quiet-cloak quiet-blue"
|
||||||
data-quiet="/static/clients/quietui@1.6.2/dist"> <!-- also quiet-dark -->
|
data-quiet="/static/clients/quietui@1.6.2/dist"> <!-- also quiet-dark -->
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Codemirror6 example using BaseX LSP</title>
|
<title>Codemirror6 example using BaseX LSP</title>
|
||||||
<link rel="icon" type="image/png" href="../favicon.png" />
|
<link rel="icon" type="image/png" href="../favicon.png" />
|
||||||
|
|
||||||
<!-- Quiet theme + autoloader -->
|
<!-- Quiet theme + autoloader -->
|
||||||
<!-- Default theme (if not already installed) -->
|
<!-- Default theme (if not already installed) -->
|
||||||
<link rel="stylesheet" href="/static/clients/quietui@1.6.2/dist/themes/quiet.css">
|
<link rel="stylesheet" href="/static/clients/quietui@1.6.2/dist/themes/quiet.css">
|
||||||
<!-- Quiet Restyle -->
|
<!-- Quiet Restyle -->
|
||||||
<link rel="stylesheet" href="/static/clients/quietui@1.6.2/dist/themes/restyle.css">
|
<link rel="stylesheet" href="/static/clients/quietui@1.6.2/dist/themes/restyle.css">
|
||||||
<script type="module" src="/static/clients/quietui@1.6.2/dist/quiet.loader.js"></script>
|
<script type="module" src="/static/clients/quietui@1.6.2/dist/quiet.loader.js"></script>
|
||||||
<script type="module" src="icons.js"></script>
|
<script type="module" src="icons.js"></script>
|
||||||
<link rel="stylesheet" href="grail.css" />
|
<link rel="stylesheet" href="grail.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="page-wrap">
|
<div class="page-wrap">
|
||||||
<header class="page-header">
|
<header class="page-header">
|
||||||
<quiet-dropdown placement="right">
|
<quiet-dropdown placement="right">
|
||||||
<quiet-button slot="trigger">File
|
<quiet-button slot="trigger">File
|
||||||
<quiet-icon slot="end" name="chevron-right"></quiet-icon>
|
<quiet-icon slot="end" name="chevron-right"></quiet-icon>
|
||||||
</quiet-button>
|
</quiet-button>
|
||||||
<quiet-dropdown-item id="bnNew">
|
<quiet-dropdown-item id="bnNew">
|
||||||
<quiet-icon slot="start" name="file"></quiet-icon>New...
|
<quiet-icon slot="start" name="file"></quiet-icon>New...
|
||||||
<div slot="details">create a new doc</div>
|
<div slot="details">create a new doc</div>
|
||||||
</quiet-dropdown-item>
|
</quiet-dropdown-item>
|
||||||
|
|
||||||
<quiet-dropdown-item id="bnRead">
|
<quiet-dropdown-item id="bnRead">
|
||||||
<quiet-icon slot="start" name="folder-open"></quiet-icon>Open...
|
<quiet-icon slot="start" name="folder-open"></quiet-icon>Open...
|
||||||
<div slot="details">select a local file</div>
|
<div slot="details">select a local file</div>
|
||||||
</quiet-dropdown-item>
|
</quiet-dropdown-item>
|
||||||
<input type="file" id="fileElem" multiple accept="*/*" style="display: none;" />
|
<input type="file" id="fileElem" multiple accept="*/*" style="display: none;" />
|
||||||
|
|
||||||
<quiet-dropdown-item id="popover__url">
|
<quiet-dropdown-item id="popover__url">
|
||||||
<quiet-icon slot="start" name="link"></quiet-icon>Url...
|
<quiet-icon slot="start" name="link"></quiet-icon>Url...
|
||||||
<div slot="details">Fetch from a url</div>
|
<div slot="details">Fetch from a url</div>
|
||||||
</quiet-dropdown-item>
|
</quiet-dropdown-item>
|
||||||
</quiet-dropdown>
|
</quiet-dropdown>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<span class="quiet-h4">XQuery 4.0 LSP client</span>
|
<span class="quiet-h4">XQuery 4.0 LSP client</span>
|
||||||
<quiet-toggle-icon id="tConnect" label="Connection status" size="lg"
|
<quiet-toggle-icon id="tConnect" label="Connection status" size="lg"
|
||||||
style="--checked-color: green;--unchecked-color: red;">
|
style="--checked-color: green;--unchecked-color: red;">
|
||||||
<quiet-icon slot="unchecked" name="network-off" family="outline"></quiet-icon>
|
<quiet-icon slot="unchecked" name="network-off" family="outline"></quiet-icon>
|
||||||
<quiet-icon slot="checked" name="network" family="outline"></quiet-icon>
|
<quiet-icon slot="checked" name="network" family="outline"></quiet-icon>
|
||||||
</quiet-toggle-icon>
|
</quiet-toggle-icon>
|
||||||
<quiet-tooltip id="tipConnect" for="tConnect">I'm a tooltip</quiet-tooltip>
|
<quiet-tooltip id="tipConnect" for="tConnect">I'm a tooltip</quiet-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<quiet-button-group>
|
<quiet-button-group>
|
||||||
<quiet-dropdown>
|
<quiet-dropdown>
|
||||||
<quiet-button slot="trigger" with-caret>Dev tools</quiet-button>
|
<quiet-button slot="trigger" with-caret>Dev tools</quiet-button>
|
||||||
<quiet-dropdown-item href="/app/home" target="lsp" rel="noreferrer noopener">
|
<quiet-dropdown-item href="/app/home" target="lsp" rel="noreferrer noopener">
|
||||||
LSP Manager <quiet-icon name="external-link" slot="icon"></quiet-icon></quiet-dropdown-item>
|
LSP Manager <quiet-icon name="external-link" slot="icon"></quiet-icon></quiet-dropdown-item>
|
||||||
<quiet-dropdown-item href="/dba/logs" target="dba" rel="noreferrer noopener">
|
<quiet-dropdown-item href="/dba/logs" target="dba" rel="noreferrer noopener">
|
||||||
Dba <quiet-icon name="external-link" slot="icon"></quiet-icon></quiet-dropdown-item>
|
Dba <quiet-icon name="external-link" slot="icon"></quiet-icon></quiet-dropdown-item>
|
||||||
<quiet-divider></quiet-divider>
|
<quiet-divider></quiet-divider>
|
||||||
</quiet-dropdown>
|
</quiet-dropdown>
|
||||||
<button popovertarget="popAbout" type="button">
|
<button popovertarget="popAbout" type="button">
|
||||||
<quiet-icon name="help"></quiet-icon>
|
<quiet-icon name="help"></quiet-icon>
|
||||||
</button>
|
</button>
|
||||||
</quiet-button-group>
|
</quiet-button-group>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
||||||
<main id="main" class="page-main" style="overflow: auto;">
|
<main id="main" class="page-main" style="overflow: auto;">
|
||||||
<quiet-toolbar style="padding:2px;background-color: var(--quiet-neutral-fill-softer);">
|
<quiet-toolbar style="padding:2px;background-color: var(--quiet-neutral-fill-softer);">
|
||||||
|
|
||||||
<quiet-button-group>
|
<quiet-button-group>
|
||||||
<quiet-button id="search" title="Search" icon-label="search" size="xs">
|
<quiet-button id="search" title="Search" icon-label="search" size="xs">
|
||||||
<quiet-icon name="search"></quiet-icon>
|
<quiet-icon name="search"></quiet-icon>
|
||||||
</quiet-button>
|
</quiet-button>
|
||||||
|
|
||||||
<quiet-button id="lint" title="Display diagnostics" icon-label="diagnostics" size="xs">
|
<quiet-button id="lint" title="Display diagnostics" icon-label="diagnostics" size="xs">
|
||||||
<quiet-icon name="message-report"></quiet-icon>
|
<quiet-icon name="message-report"></quiet-icon>
|
||||||
</quiet-button>
|
</quiet-button>
|
||||||
|
|
||||||
<quiet-button id="symbols2" title="symbols" icon-label="Symbols" size="xs">
|
<quiet-button id="symbols2" title="symbols" icon-label="Symbols" size="xs">
|
||||||
<quiet-icon name="icons"></quiet-icon>
|
<quiet-icon name="icons"></quiet-icon>
|
||||||
</quiet-button>
|
</quiet-button>
|
||||||
|
|
||||||
<quiet-button id="format" type="button" title="Format (Shift-Alt-f)" icon-label="Format" size="xs">
|
<quiet-button id="format" type="button" title="Format (Shift-Alt-f)" icon-label="Format" size="xs">
|
||||||
<quiet-icon name="align-justified"></quiet-icon>
|
<quiet-icon name="align-justified"></quiet-icon>
|
||||||
</quiet-button>
|
</quiet-button>
|
||||||
|
|
||||||
</quiet-button-group>
|
</quiet-button-group>
|
||||||
|
|
||||||
<quiet-button-group>
|
<quiet-button-group>
|
||||||
<button id="sync" title="Sync changes to server">
|
<button id="sync" title="Sync changes to server">
|
||||||
<i class="codicon codicon-sync"></i>
|
<i class="codicon codicon-sync"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button id="cmdList" title="Command and key mapping help">
|
<button id="cmdList" title="Command and key mapping help">
|
||||||
<i class="codicon codicon-record-keys"></i>
|
<i class="codicon codicon-record-keys"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button" popovertarget="popSettings" title="Settings">
|
<button type="button" popovertarget="popSettings" title="Settings">
|
||||||
<i class="codicon codicon-settings"></i>
|
<i class="codicon codicon-settings"></i>
|
||||||
</button>
|
</button>
|
||||||
<button id="fullscreen" title="Full screen editor" type="button">
|
<button id="fullscreen" title="Full screen editor" type="button">
|
||||||
<i class="codicon codicon-screen-full"></i>
|
<i class="codicon codicon-screen-full"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button id="bnSave" type="button" title="save view">
|
<button id="bnSave" type="button" title="save view">
|
||||||
<i class="codicon codicon-git-stash"></i></button>
|
<i class="codicon codicon-git-stash"></i></button>
|
||||||
|
|
||||||
<button id="bnLoad" type="button" title="load view">
|
<button id="bnLoad" type="button" title="load view">
|
||||||
<i class="codicon codicon-git-stash-pop"></i></button>
|
<i class="codicon codicon-git-stash-pop"></i></button>
|
||||||
|
|
||||||
<button id="bnWordAt" type="button" title="word at">
|
<button id="bnWordAt" type="button" title="word at">
|
||||||
<i class="codicon codicon-whole-word"></i></button>
|
<i class="codicon codicon-whole-word"></i></button>
|
||||||
|
|
||||||
|
|
||||||
<quiet-button id="bnDebug" title="Debug " icon-label="debug" size="xs">
|
<quiet-button id="bnDebug" title="Debug " icon-label="debug" size="xs">
|
||||||
<quiet-icon library="codicon" name="debug"></quiet-icon>
|
<quiet-icon library="codicon" name="debug"></quiet-icon>
|
||||||
</quiet-button>
|
</quiet-button>
|
||||||
</quiet-button-group>
|
</quiet-button-group>
|
||||||
</quiet-toolbar>
|
</quiet-toolbar>
|
||||||
|
|
||||||
<!-- Editor goes in here -->
|
<!-- Editor goes in here -->
|
||||||
<div id="editor"></div>
|
<div id="editor"></div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<aside class="page-sidebar">
|
<aside class="page-sidebar">
|
||||||
|
|
||||||
<details id="workspacePanel" open="open">
|
<details id="workspacePanel" open="open">
|
||||||
<summary class='bg-info'>WORKSPACE <i class='codicon codicon-kebab-vertical' style="float:right"></i>
|
<summary class='bg-info'>WORKSPACE <i class='codicon codicon-kebab-vertical' style="float:right"></i>
|
||||||
</summary>
|
</summary>
|
||||||
<quiet-listbox size="sm">
|
<quiet-listbox size="sm">
|
||||||
<quiet-listbox-item value="file:///some/file.xqm">file:///some/file.xqm</quiet-listbox-item>
|
<quiet-listbox-item value="file:///some/file.xqm">file:///some/file.xqm</quiet-listbox-item>
|
||||||
<quiet-listbox-item value="2">Luna</quiet-listbox-item>
|
<quiet-listbox-item value="2">Luna</quiet-listbox-item>
|
||||||
<quiet-listbox-item value="3">Meowy McGee</quiet-listbox-item>
|
<quiet-listbox-item value="3">Meowy McGee</quiet-listbox-item>
|
||||||
<quiet-listbox-item value="4">Milo</quiet-listbox-item>
|
<quiet-listbox-item value="4">Milo</quiet-listbox-item>
|
||||||
<quiet-listbox-item value="5">Mittens</quiet-listbox-item>
|
<quiet-listbox-item value="5">Mittens</quiet-listbox-item>
|
||||||
<quiet-listbox-item value="6">Oliver</quiet-listbox-item>
|
<quiet-listbox-item value="6">Oliver</quiet-listbox-item>
|
||||||
|
|
||||||
</quiet-listbox>
|
</quiet-listbox>
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details id="symPanel">
|
<details id="symPanel">
|
||||||
<summary>OUTLINE
|
<summary>OUTLINE
|
||||||
<quiet-dropdown id="symOptions" style="display:inline-block;float:right;">
|
<quiet-dropdown id="symOptions" style="display:inline-block;float:right;">
|
||||||
<quiet-icon id="symTrigger" name="dots-vertical" slot="trigger"></quiet-icon>
|
<quiet-icon id="symTrigger" name="dots-vertical" slot="trigger"></quiet-icon>
|
||||||
<quiet-dropdown-item type="checkbox" value="canvas" checked>Follow cursor</quiet-dropdown-item>
|
<quiet-dropdown-item type="checkbox" value="canvas" checked>Follow cursor</quiet-dropdown-item>
|
||||||
|
|
||||||
<quiet-divider></quiet-divider>
|
<quiet-divider></quiet-divider>
|
||||||
<quiet-dropdown-item type="checkbox" value="position" checked>sort by:
|
<quiet-dropdown-item type="checkbox" value="position" checked>sort by:
|
||||||
Position</quiet-dropdown-item>
|
Position</quiet-dropdown-item>
|
||||||
<quiet-dropdown-item type="checkbox" value="name">sort by: Name</quiet-dropdown-item>
|
<quiet-dropdown-item type="checkbox" value="name">sort by: Name</quiet-dropdown-item>
|
||||||
<quiet-dropdown-item type="checkbox" value="category">sort by: Category</quiet-dropdown-item>
|
<quiet-dropdown-item type="checkbox" value="category">sort by: Category</quiet-dropdown-item>
|
||||||
</quiet-dropdown>
|
</quiet-dropdown>
|
||||||
</summary>
|
</summary>
|
||||||
<qd-list id="symList" style="flex-grow:1;"></qd-list>
|
<qd-list id="symList" style="flex-grow:1;"></qd-list>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details id="msgPanel">
|
<details id="msgPanel">
|
||||||
<summary>MESSAGES
|
<summary>MESSAGES
|
||||||
<i id="msgIcon" class='codicon codicon-kebab-vertical' style="float:right"></i>
|
<i id="msgIcon" class='codicon codicon-kebab-vertical' style="float:right"></i>
|
||||||
</summary>
|
</summary>
|
||||||
<qd-list id="msgList" style="flex-grow:1;"></qd-list>
|
<qd-list id="msgList" style="flex-grow:1;"></qd-list>
|
||||||
</details>
|
</details>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<footer class="page-footer">
|
<footer class="page-footer">
|
||||||
<div style="display:flex;">
|
<div style="display:flex;">
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="iFile">File:</label>
|
<label for="iFile">File:</label>
|
||||||
<input id="iFile" type="url" value="file:///some/file.xqm"
|
<input id="iFile" type="url" value="file:///some/file.xqm"
|
||||||
style="width:20em;display:inline-block;" />
|
style="width:20em;display:inline-block;" />
|
||||||
|
|
||||||
<label for="symbols">Symbols:</label>
|
<label for="symbols">Symbols:</label>
|
||||||
<select id="symbols" disabled="disabled" style="width:10em;display:inline-block;"></select>
|
<select id="symbols" disabled="disabled" style="width:10em;display:inline-block;"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<quiet-relative-time live id="relative-time__live" numeric='always' format='short' style="width:10em;"></quiet-relative-time>
|
<quiet-relative-time live id="relative-time__live" numeric='always' format='short' style="width:10em;"></quiet-relative-time>
|
||||||
<select id="language" style="width:10em;display:inline-block;">
|
<select id="language" style="width:10em;display:inline-block;">
|
||||||
<option selected>Language</option>
|
<option selected>Language</option>
|
||||||
<option value="plaintext">plaintext</option>
|
<option value="plaintext">plaintext</option>
|
||||||
<option value="xquery">xquery</option>
|
<option value="xquery">xquery</option>
|
||||||
<option value="xml">xml</option>
|
<option value="xml">xml</option>
|
||||||
</select>
|
</select>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- dialogs -->
|
<!-- dialogs -->
|
||||||
<quiet-popover id="popWeb" for="popover__url">
|
<quiet-popover id="popWeb" for="popover__url">
|
||||||
<div style="display:flex;background: #ffecb3;">
|
<div style="display:flex;background: #ffecb3;">
|
||||||
<div style="flex: 1 1 auto;">Load a document from the web</div>
|
<div style="flex: 1 1 auto;">Load a document from the web</div>
|
||||||
<quiet-button icon-label="Close" appearance="text" data-popover="close">
|
<quiet-button icon-label="Close" appearance="text" data-popover="close">
|
||||||
<quiet-icon name="x"></quiet-icon>
|
<quiet-icon name="x"></quiet-icon>
|
||||||
</quiet-button>
|
</quiet-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form id="popUrl">
|
<form id="popUrl">
|
||||||
<quiet-text-field type="url" name="url" label="URL to fetch" placeholder="http://..." with-clear required
|
<quiet-text-field type="url" name="url" label="URL to fetch" placeholder="http://..." with-clear required
|
||||||
style="width: 20em;">
|
style="width: 20em;">
|
||||||
<datalist>
|
<datalist>
|
||||||
<option
|
<option
|
||||||
value="https://raw.githubusercontent.com/expkg-zone58/pdfbox/refs/heads/main/src/Pdfbox3.xqm">
|
value="https://raw.githubusercontent.com/expkg-zone58/pdfbox/refs/heads/main/src/Pdfbox3.xqm">
|
||||||
Pdfbox3.xqm (expkg-zone58/pdfbox) </option>
|
Pdfbox3.xqm (expkg-zone58/pdfbox) </option>
|
||||||
<option
|
<option
|
||||||
value="https://raw.githubusercontent.com/Quodatum/xqdoca/refs/heads/master/src/main/lib/model.xqm">
|
value="https://raw.githubusercontent.com/Quodatum/xqdoca/refs/heads/master/src/main/lib/model.xqm">
|
||||||
model.xqm (Quodatum/xqdoca)</option>
|
model.xqm (Quodatum/xqdoca)</option>
|
||||||
<option
|
<option
|
||||||
value="https://git.quodatum.duckdns.org/api/v1/repos/quodatum/basex-lsp/raw/webapp/lsp/lsp-text.xqm">
|
value="https://git.quodatum.duckdns.org/api/v1/repos/quodatum/basex-lsp/raw/webapp/lsp/lsp-text.xqm">
|
||||||
lsp-text.xqm (quodatum/basex-lsp FORGEIO)</option>
|
lsp-text.xqm (quodatum/basex-lsp FORGEIO)</option>
|
||||||
<option
|
<option
|
||||||
value="https://raw.githubusercontent.com/dnovatchev/Articles/refs/heads/main/Generators/Code/generator.xq">
|
value="https://raw.githubusercontent.com/dnovatchev/Articles/refs/heads/main/Generators/Code/generator.xq">
|
||||||
generator.xquery</option>
|
generator.xquery</option>
|
||||||
</datalist>
|
</datalist>
|
||||||
</quiet-text-field>
|
</quiet-text-field>
|
||||||
<quiet-button type="submit" variant="primary">Fetch</quiet-button>
|
<quiet-button type="submit" variant="primary">Fetch</quiet-button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</quiet-popover>
|
</quiet-popover>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Popovers -->
|
<!-- Popovers -->
|
||||||
|
|
||||||
<dialog id="popConnect" popover>
|
<dialog id="popConnect" popover>
|
||||||
<form>
|
<form>
|
||||||
<header>Connect to LSP
|
<header>Connect to LSP
|
||||||
<button type="button" class="btn-close" aria-label="Close"
|
<button type="button" class="btn-close" aria-label="Close"
|
||||||
onclick="$('popConnect').hidePopover(); "></button>
|
onclick="$('popConnect').hidePopover(); "></button>
|
||||||
</header>
|
</header>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div id="state">🔴</div>
|
<div id="state">🔴</div>
|
||||||
<input id="iServer" type="text" style="width:25em" />
|
<input id="iServer" type="text" style="width:25em" />
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button id="connect">connect</button>
|
<button id="connect">connect</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<dialog id="popCmds" popover>
|
<dialog id="popCmds" popover>
|
||||||
<form>
|
<form>
|
||||||
<header>Commands and keys
|
<header>Commands and keys
|
||||||
<button type="button" class="btn-close" aria-label="Close"
|
<button type="button" class="btn-close" aria-label="Close"
|
||||||
onclick="$('popCmds').hidePopover(); "></button>
|
onclick="$('popCmds').hidePopover(); "></button>
|
||||||
</header>
|
</header>
|
||||||
<div id="popHelpInfo" class="modal-body" style="height: 50vh;overflow:scroll;">
|
<div id="popHelpInfo" class="modal-body" style="height: 50vh;overflow:scroll;">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
<dialog id="popAbout" popover>
|
<dialog id="popAbout" popover>
|
||||||
<form>
|
<form>
|
||||||
<header>Help</header>
|
<header>Help</header>
|
||||||
<div class="modal-body" style="height: 50vh;overflow:scroll;">
|
<div class="modal-body" style="height: 50vh;overflow:scroll;">
|
||||||
<p>TODO help info</p>
|
<p>TODO help info</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
<!-- <popup-info id="popHelp">hhhh</popup-info> -->
|
<!-- <popup-info id="popHelp">hhhh</popup-info> -->
|
||||||
|
|
||||||
<dialog id="popSettings" popover>
|
<dialog id="popSettings" popover>
|
||||||
<form id="fSettings">
|
<form id="fSettings">
|
||||||
<header>Editor configuration
|
<header>Editor configuration
|
||||||
<button type="button" class="btn-close" aria-label="Close"
|
<button type="button" class="btn-close" aria-label="Close"
|
||||||
onclick="$('popSettings').hidePopover(); "></button>
|
onclick="$('popSettings').hidePopover(); "></button>
|
||||||
</header>
|
</header>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|
||||||
<div class="mb-3 form-check">
|
<div class="mb-3 form-check">
|
||||||
<input name="wrapLines" type="checkbox" class="form-check-input" id="lineWrap">
|
<input name="wrapLines" type="checkbox" class="form-check-input" id="lineWrap">
|
||||||
<label class="form-check-label" for="lineWrap">Wrap lines</label>
|
<label class="form-check-label" for="lineWrap">Wrap lines</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3 form-check">
|
<div class="mb-3 form-check">
|
||||||
<input name="highlightWhitespace" type="checkbox" class="form-check-input" id="highlightWhitespace">
|
<input name="highlightWhitespace" type="checkbox" class="form-check-input" id="highlightWhitespace">
|
||||||
<label class="form-check-label" for="highlightWhitespace">highlight Whitespace</label>
|
<label class="form-check-label" for="highlightWhitespace">highlight Whitespace</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3 form-check">
|
<div class="mb-3 form-check">
|
||||||
<input name="minimap" type="checkbox" class="form-check-input" id="minimap">
|
<input name="minimap" type="checkbox" class="form-check-input" id="minimap">
|
||||||
<label class="form-check-label" for="minimap">Show minimap</label>
|
<label class="form-check-label" for="minimap">Show minimap</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" class="btn btn-primary">Apply</button>
|
<button type="submit" class="btn btn-primary">Apply</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
<!-- CodeMirror 6 -->
|
<!-- CodeMirror 6 -->
|
||||||
<script src="./lsp.bundle.js"></script>
|
<script src="./lsp.bundle.js"></script>
|
||||||
<script src="./script.js"></script>
|
<script src="./script.js"></script>
|
||||||
<script src="./wc-qd-list.js"></script>
|
<script src="./wc-qd-list.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { registerIconLibrary } from '/static/clients/quietui@1.6.2/dist/quiet.loader.js';
|
import { registerIconLibrary } from '/static/clients/quietui@1.6.2/dist/quiet.loader.js';
|
||||||
|
|
||||||
registerIconLibrary('codicon', {
|
registerIconLibrary('codicon', {
|
||||||
resolve: (name, family) => {
|
resolve: (name, family) => {
|
||||||
return `/static/clients/codicon@0.0.40/icons/${name}.svg`
|
return `/static/clients/codicon@0.0.40/icons/${name}.svg`
|
||||||
}});
|
}});
|
||||||
|
|
@ -1,196 +1,196 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Codemirror6 example using BaseX LSP</title>
|
<title>Codemirror6 example using BaseX LSP</title>
|
||||||
<link rel="icon" type="image/png" href="../favicon.png" />
|
<link rel="icon" type="image/png" href="../favicon.png" />
|
||||||
<link href="../bootstrap@5.3.7.css" rel="stylesheet" />
|
<link href="../bootstrap@5.3.7.css" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="grail.css" />
|
<link rel="stylesheet" href="grail.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="page-wrap">
|
<div class="page-wrap">
|
||||||
<header class="page-header">
|
<header class="page-header">
|
||||||
<nav class="navbar bg-body-tertiary">
|
<nav class="navbar bg-body-tertiary">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a id="help" class="navbar-brand">XQuery 4.0 LSP client
|
<a id="help" class="navbar-brand">XQuery 4.0 LSP client
|
||||||
<button id="popcon" popovertarget="popConnect" class="btn btn-danger">
|
<button id="popcon" popovertarget="popConnect" class="btn btn-danger">
|
||||||
<i class="codicon codicon-vm-outline"></i>
|
<i class="codicon codicon-vm-outline"></i>
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" aria-current="page" href="#">Editor</a>
|
<a class="nav-link active" aria-current="page" href="#">Editor</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="#">Msgs</a>
|
<a class="nav-link" href="#">Msgs</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="/dba/logs" target="dba">Dba</a>
|
<a class="nav-link" href="/dba/logs" target="dba">Dba</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
|
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
<nav class="page-nav">
|
<nav class="page-nav">
|
||||||
<div class="navbar py-0 bg-light">
|
<div class="navbar py-0 bg-light">
|
||||||
|
|
||||||
<div class="btn-group mr-2" role="group" aria-label="First group">
|
<div class="btn-group mr-2" role="group" aria-label="First group">
|
||||||
<label for="file">File:</label>
|
<label for="file">File:</label>
|
||||||
<input id="iFile" type="url" value="file:///some/file.xqm" />
|
<input id="iFile" type="url" value="file:///some/file.xqm" />
|
||||||
|
|
||||||
<label for="symbols">Symbols:</label><select id="symbols" disabled="disabled"></select>
|
<label for="symbols">Symbols:</label><select id="symbols" disabled="disabled"></select>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group btn-group-sm " role="group" aria-label="Second group">
|
<div class="btn-group btn-group-sm " role="group" aria-label="Second group">
|
||||||
|
|
||||||
<button id="search" title="Search" type="button" class="btn btn-light"><i
|
<button id="search" title="Search" type="button" class="btn btn-light"><i
|
||||||
class="codicon codicon-search"></i></button>
|
class="codicon codicon-search"></i></button>
|
||||||
|
|
||||||
<button id="lint" title="Display diagnostics" type="button" class="btn btn-light"><i
|
<button id="lint" title="Display diagnostics" type="button" class="btn btn-light"><i
|
||||||
class="codicon codicon-report"></i></button>
|
class="codicon codicon-report"></i></button>
|
||||||
|
|
||||||
<button id="symbols2" type="button" class="btn btn-light" title="symbols">
|
<button id="symbols2" type="button" class="btn btn-light" title="symbols">
|
||||||
<i class="codicon codicon-symbol-misc"></i></button>
|
<i class="codicon codicon-symbol-misc"></i></button>
|
||||||
|
|
||||||
<button id="format" type="button" class="btn btn-light" title="Format (Shift-Alt-f)"><i
|
<button id="format" type="button" class="btn btn-light" title="Format (Shift-Alt-f)"><i
|
||||||
class="codicon codicon-list-flat"></i></button>
|
class="codicon codicon-list-flat"></i></button>
|
||||||
|
|
||||||
<button id="sync" title="Sync changes to server" type="button" class="btn btn-light">
|
<button id="sync" title="Sync changes to server" type="button" class="btn btn-light">
|
||||||
<i class="codicon codicon-sync"></i>
|
<i class="codicon codicon-sync"></i>
|
||||||
</button>
|
</button>
|
||||||
<button id="fullscreen" title="Full screen editor" type="button" class="btn btn-light">
|
<button id="fullscreen" title="Full screen editor" type="button" class="btn btn-light">
|
||||||
<i class="codicon codicon-screen-full"></i>
|
<i class="codicon codicon-screen-full"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button" class="btn btn-light" popovertarget="popSettings" title="Settings">
|
<button type="button" class="btn btn-light" popovertarget="popSettings" title="Settings">
|
||||||
<i class="codicon codicon-settings"></i></button>
|
<i class="codicon codicon-settings"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group" role="group" aria-label="Third group">
|
<div class="btn-group" role="group" aria-label="Third group">
|
||||||
|
|
||||||
<button id="syntax" type="button" class="btn btn-light" title="Unused"><i
|
<button id="syntax" type="button" class="btn btn-light" title="Unused"><i
|
||||||
class="codicon codicon-comment"></i></button>
|
class="codicon codicon-comment"></i></button>
|
||||||
|
|
||||||
<button id="cmd" type="button" class="btn btn-light" title="Cmd list to console">
|
<button id="cmd" type="button" class="btn btn-light" title="Cmd list to console">
|
||||||
<i class="codicon codicon-debug-console"></i>
|
<i class="codicon codicon-debug-console"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button id="wordAt" type="button" class="btn btn-light" title="word at">
|
<button id="wordAt" type="button" class="btn btn-light" title="word at">
|
||||||
<i>1</i></button>
|
<i>1</i></button>
|
||||||
|
|
||||||
|
|
||||||
<button id="unused3" type="button" class="btn btn-light" title="unused3">
|
<button id="unused3" type="button" class="btn btn-light" title="unused3">
|
||||||
<i>3</i></button>
|
<i>3</i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="page-main" style="overflow: auto;">
|
<main class="page-main" style="overflow: auto;">
|
||||||
<!-- Editor goes in here -->
|
<!-- Editor goes in here -->
|
||||||
<div id="editor"></div>
|
<div id="editor"></div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<aside class="page-sidebar">
|
<aside class="page-sidebar">
|
||||||
|
|
||||||
<details id="workspacePanel" open="open" >
|
<details id="workspacePanel" open="open" >
|
||||||
<summary class='bg-info'>Workspace <b>0</b></summary>
|
<summary class='bg-info'>Workspace <b>0</b></summary>
|
||||||
<select id="load">
|
<select id="load">
|
||||||
<option selected value="">load..</option>
|
<option selected value="">load..</option>
|
||||||
<optgroup label="XQuery3">
|
<optgroup label="XQuery3">
|
||||||
<option
|
<option
|
||||||
value="https://raw.githubusercontent.com/expkg-zone58/pdfbox/refs/heads/main/src/Pdfbox3.xqm">
|
value="https://raw.githubusercontent.com/expkg-zone58/pdfbox/refs/heads/main/src/Pdfbox3.xqm">
|
||||||
Pdfbox3.xqm</option>
|
Pdfbox3.xqm</option>
|
||||||
<option
|
<option
|
||||||
value="https://raw.githubusercontent.com/Quodatum/xqdoca/refs/heads/master/src/main/lib/model.xqm">
|
value="https://raw.githubusercontent.com/Quodatum/xqdoca/refs/heads/master/src/main/lib/model.xqm">
|
||||||
model.xqm</option>
|
model.xqm</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup label="XQuery4">
|
<optgroup label="XQuery4">
|
||||||
<option
|
<option
|
||||||
value="https://git.quodatum.duckdns.org/quodatum/basex-lsp/raw/branch/main/webapp/lsp/lsp-text.xqm">
|
value="https://git.quodatum.duckdns.org/quodatum/basex-lsp/raw/branch/main/webapp/lsp/lsp-text.xqm">
|
||||||
lsp-text.xqm</option>
|
lsp-text.xqm</option>
|
||||||
<option value="../../../lsp/lsp-text.xqm">
|
<option value="../../../lsp/lsp-text.xqm">
|
||||||
lsp-text.xqm</option>
|
lsp-text.xqm</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
|
|
||||||
<optgroup label="xpath">
|
<optgroup label="xpath">
|
||||||
<option
|
<option
|
||||||
value="https://raw.githubusercontent.com/dnovatchev/Articles/refs/heads/main/Generators/Code/generator.xq">
|
value="https://raw.githubusercontent.com/dnovatchev/Articles/refs/heads/main/Generators/Code/generator.xq">
|
||||||
generator.xquery</option>
|
generator.xquery</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<ul id="traffic" style="overflow: scroll;">
|
<ul id="traffic" style="overflow: scroll;">
|
||||||
<li>-</li>
|
<li>-</li>
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details id="symPanel">
|
<details id="symPanel">
|
||||||
<summary >OutLine <b>0</b></summary>
|
<summary >OutLine <b>0</b></summary>
|
||||||
<json-list id="symList" ></json-list>
|
<json-list id="symList" ></json-list>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details id="msgPanel" >
|
<details id="msgPanel" >
|
||||||
<summary >Messages <b>0</b></summary>
|
<summary >Messages <b>0</b></summary>
|
||||||
<div id="msg">(msgs)<i class='codicon codicon-symbol-method'></i></div>
|
<div id="msg">(msgs)<i class='codicon codicon-symbol-method'></i></div>
|
||||||
</details>
|
</details>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<footer class="page-footer">
|
<footer class="page-footer">
|
||||||
Footer <select id="language">
|
Footer <select id="language">
|
||||||
<option selected>Language</option>
|
<option selected>Language</option>
|
||||||
<option value="plaintext">plaintext</option>
|
<option value="plaintext">plaintext</option>
|
||||||
<option value="xquery">xquery</option>
|
<option value="xquery">xquery</option>
|
||||||
<option value="xml">xml</option>
|
<option value="xml">xml</option>
|
||||||
</select>
|
</select>
|
||||||
<button popovertarget="popHelp"><i class="codicon codicon-info"></i></button>
|
<button popovertarget="popHelp"><i class="codicon codicon-info"></i></button>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
<!-- Popovers -->
|
<!-- Popovers -->
|
||||||
<dialog id="popConnect" popover>
|
<dialog id="popConnect" popover>
|
||||||
<header>Connect to LSP
|
<header>Connect to LSP
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</header>
|
</header>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div id="state">🔴</div>
|
<div id="state">🔴</div>
|
||||||
<input id="iServer" type="text" style="width:25em" />
|
<input id="iServer" type="text" style="width:25em" />
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button id="connect">connect</button>
|
<button id="connect">connect</button>
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<!-- <popup-info id="popHelp">hhhh</popup-info> -->
|
<!-- <popup-info id="popHelp">hhhh</popup-info> -->
|
||||||
|
|
||||||
<dialog id="popSettings" popover>
|
<dialog id="popSettings" popover>
|
||||||
<form id="fSettings">
|
<form id="fSettings">
|
||||||
<header>Editor configuration
|
<header>Editor configuration
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"
|
||||||
onclick="$('popSettings').hidePopover(); "></button>
|
onclick="$('popSettings').hidePopover(); "></button>
|
||||||
</header>
|
</header>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|
||||||
<div class="mb-3 form-check">
|
<div class="mb-3 form-check">
|
||||||
<input name="wrap-lines" type="checkbox" class="form-check-input" id="exampleCheck1">
|
<input name="wrap-lines" type="checkbox" class="form-check-input" id="exampleCheck1">
|
||||||
<label class="form-check-label" for="exampleCheck1">Wrap lines</label>
|
<label class="form-check-label" for="exampleCheck1">Wrap lines</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" class="btn btn-primary">Apply</button>
|
<button type="submit" class="btn btn-primary">Apply</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
<!-- CodeMirror 6 -->
|
<!-- CodeMirror 6 -->
|
||||||
<script src="./lsp.bundle.js"></script>
|
<script src="./lsp.bundle.js"></script>
|
||||||
<script src="./script.js"></script>
|
<script src="./script.js"></script>
|
||||||
<script src="./list.js"></script>
|
<script src="./list.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -31344,103 +31344,103 @@ ${text}</tr>
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let create = (v) => {
|
let create = (v) => {
|
||||||
const dom = document.createElement('div');
|
const dom = document.createElement('div');
|
||||||
return { dom }
|
return { dom }
|
||||||
};
|
};
|
||||||
const compartment = new Compartment();
|
const compartment = new Compartment();
|
||||||
let curOpts = {
|
let curOpts = {
|
||||||
lineWrap: true,
|
lineWrap: true,
|
||||||
minimap: true,
|
minimap: true,
|
||||||
highlightWhitespace: true
|
highlightWhitespace: true
|
||||||
};
|
};
|
||||||
// array of extensions reflecting opts
|
// array of extensions reflecting opts
|
||||||
function optExts(opts) {
|
function optExts(opts) {
|
||||||
let exts = [];
|
let exts = [];
|
||||||
if (opts.lineWrap) exts.push(EditorView.lineWrapping);
|
if (opts.lineWrap) exts.push(EditorView.lineWrapping);
|
||||||
if (opts.highlightWhitespace) exts.push(highlightWhitespace());
|
if (opts.highlightWhitespace) exts.push(highlightWhitespace());
|
||||||
if (opts.minimap) exts.push(
|
if (opts.minimap) exts.push(
|
||||||
showMinimap.compute(['doc'], (state) => {
|
showMinimap.compute(['doc'], (state) => {
|
||||||
return {
|
return {
|
||||||
create,
|
create,
|
||||||
/* optional showOverlay: 'mouse-over' */
|
/* optional showOverlay: 'mouse-over' */
|
||||||
displayText: 'characters'
|
displayText: 'characters'
|
||||||
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
return exts
|
return exts
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCompartment(opts) {
|
function updateCompartment(opts) {
|
||||||
view.dispatch({
|
view.dispatch({
|
||||||
effects: [compartment.reconfigure(optExts(opts))]
|
effects: [compartment.reconfigure(optExts(opts))]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// return promise with socket map or reject if no connect
|
// return promise with socket map or reject if no connect
|
||||||
function simpleWebSocketTransport(uri) {
|
function simpleWebSocketTransport(uri) {
|
||||||
let handlers = [];
|
let handlers = [];
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
let sock = new WebSocket(uri);
|
let sock = new WebSocket(uri);
|
||||||
|
|
||||||
sock.onmessage = e => { for (let h of handlers) h(e.data.toString()); };
|
sock.onmessage = e => { for (let h of handlers) h(e.data.toString()); };
|
||||||
sock.onerror = e => reject(e);
|
sock.onerror = e => reject(e);
|
||||||
sock.onopen = () => resolve({
|
sock.onopen = () => resolve({
|
||||||
socket: sock,
|
socket: sock,
|
||||||
send: (message) => sock.send(message),
|
send: (message) => sock.send(message),
|
||||||
subscribe: (handler) => handlers.push(handler),
|
subscribe: (handler) => handlers.push(handler),
|
||||||
unsubscribe: (handler) => handlers = handlers.filter(h => h != handler)
|
unsubscribe: (handler) => handlers = handlers.filter(h => h != handler)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const baseExts = [
|
const baseExts = [
|
||||||
lineNumbers(),
|
lineNumbers(),
|
||||||
highlightActiveLineGutter(),
|
highlightActiveLineGutter(),
|
||||||
history(),
|
history(),
|
||||||
foldGutter(),
|
foldGutter(),
|
||||||
lintGutter(),
|
lintGutter(),
|
||||||
drawSelection(),
|
drawSelection(),
|
||||||
dropCursor(),
|
dropCursor(),
|
||||||
EditorState.allowMultipleSelections.of(true),
|
EditorState.allowMultipleSelections.of(true),
|
||||||
tooltips({ }), // clipped
|
tooltips({ }), // clipped
|
||||||
keymap.of([indentWithTab]),
|
keymap.of([indentWithTab]),
|
||||||
indentOnInput(),
|
indentOnInput(),
|
||||||
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
||||||
bracketMatching(),
|
bracketMatching(),
|
||||||
closeBrackets(),
|
closeBrackets(),
|
||||||
autocompletion(),
|
autocompletion(),
|
||||||
rectangularSelection(),
|
rectangularSelection(),
|
||||||
crosshairCursor(),
|
crosshairCursor(),
|
||||||
highlightActiveLine(),
|
highlightActiveLine(),
|
||||||
highlightSelectionMatches(),
|
highlightSelectionMatches(),
|
||||||
keymap.of([
|
keymap.of([
|
||||||
...closeBracketsKeymap,
|
...closeBracketsKeymap,
|
||||||
...defaultKeymap,
|
...defaultKeymap,
|
||||||
...searchKeymap,
|
...searchKeymap,
|
||||||
...historyKeymap,
|
...historyKeymap,
|
||||||
...foldKeymap,
|
...foldKeymap,
|
||||||
...completionKeymap,
|
...completionKeymap,
|
||||||
...lintKeymap
|
...lintKeymap
|
||||||
]),
|
]),
|
||||||
StreamLanguage.define(xQuery),
|
StreamLanguage.define(xQuery),
|
||||||
compartment.of(optExts(curOpts))
|
compartment.of(optExts(curOpts))
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// map cmd->{keybings,fn}
|
// map cmd->{keybings,fn}
|
||||||
function listCommands(view) {
|
function listCommands(view) {
|
||||||
const commands = new Map();
|
const commands = new Map();
|
||||||
const keymaps = view.state.facet(keymap);
|
const keymaps = view.state.facet(keymap);
|
||||||
for (let km of keymaps) {
|
for (let km of keymaps) {
|
||||||
for (let binding of km) {
|
for (let binding of km) {
|
||||||
if (binding.run && binding.run.name) {
|
if (binding.run && binding.run.name) {
|
||||||
commands.set(binding.run.name, { key: binding.key, fn: binding.run });
|
commands.set(binding.run.name, { key: binding.key, fn: binding.run });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.EditorState = EditorState;
|
exports.EditorState = EditorState;
|
||||||
|
|
|
||||||
|
|
@ -1,246 +1,246 @@
|
||||||
|
|
||||||
const view = new lsp.EditorView({
|
const view = new lsp.EditorView({
|
||||||
extensions: lsp.baseExts,
|
extensions: lsp.baseExts,
|
||||||
parent: document.getElementById("editor")
|
parent: document.getElementById("editor")
|
||||||
});
|
});
|
||||||
let doc = "xquery version '3.1';\n(:~ comment:)\nmodule namespace pdfbox='ns';\n";
|
let doc = "xquery version '3.1';\n(:~ comment:)\nmodule namespace pdfbox='ns';\n";
|
||||||
var client; // https://codemirror.net/docs/ref/#lsp-client
|
var client; // https://codemirror.net/docs/ref/#lsp-client
|
||||||
|
|
||||||
var workspace = {
|
var workspace = {
|
||||||
"file:///some/file.xqm": null
|
"file:///some/file.xqm": null
|
||||||
};
|
};
|
||||||
|
|
||||||
function $(id) { return document.getElementById(id) };
|
function $(id) { return document.getElementById(id) };
|
||||||
|
|
||||||
// Load saved content from localStorage when the page loads
|
// Load saved content from localStorage when the page loads
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
|
|
||||||
const savedText = localStorage.getItem('code');
|
const savedText = localStorage.getItem('code');
|
||||||
if (savedText) doc = savedText;
|
if (savedText) doc = savedText;
|
||||||
let svr = localStorage.getItem('lsp');
|
let svr = localStorage.getItem('lsp');
|
||||||
if (!svr) {
|
if (!svr) {
|
||||||
let x = new URL(window.location.href);
|
let x = new URL(window.location.href);
|
||||||
x.protocol = "ws";
|
x.protocol = "ws";
|
||||||
x.pathname = "ws/lsp"
|
x.pathname = "ws/lsp"
|
||||||
svr = x.href;
|
svr = x.href;
|
||||||
}
|
}
|
||||||
$("iServer").value = svr;
|
$("iServer").value = svr;
|
||||||
formFromStore('fSettings');
|
formFromStore('fSettings');
|
||||||
view.setState(lsp.EditorState.create({ doc: doc, extensions: lsp.baseExts }));
|
view.setState(lsp.EditorState.create({ doc: doc, extensions: lsp.baseExts }));
|
||||||
lsp.updateCompartment(objectFromForm('fSettings'))
|
lsp.updateCompartment(objectFromForm('fSettings'))
|
||||||
connect();
|
connect();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Save content to localStorage when the page is about to unload
|
// Save content to localStorage when the page is about to unload
|
||||||
window.addEventListener('beforeunload', () => {
|
window.addEventListener('beforeunload', () => {
|
||||||
const doc = view.state.doc.toString();
|
const doc = view.state.doc.toString();
|
||||||
localStorage.setItem('code', doc);
|
localStorage.setItem('code', doc);
|
||||||
localStorage.setItem('lsp', $("iServer").value);
|
localStorage.setItem('lsp', $("iServer").value);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("connect").onclick = e => { e.preventDefault(); connect() };
|
$("connect").onclick = e => { e.preventDefault(); connect() };
|
||||||
|
|
||||||
$("symTrigger").onclick = e => { e.preventDefault(); };
|
$("symTrigger").onclick = e => { e.preventDefault(); };
|
||||||
$("symOptions").onclick = e => { e.preventDefault(); };
|
$("symOptions").onclick = e => { e.preventDefault(); };
|
||||||
$("bnNew").onclick = e => {
|
$("bnNew").onclick = e => {
|
||||||
let name = prompt("New file name?", "untitled.xq");
|
let name = prompt("New file name?", "untitled.xq");
|
||||||
if (name === null) return;
|
if (name === null) return;
|
||||||
docSwitch("", name);
|
docSwitch("", name);
|
||||||
};
|
};
|
||||||
|
|
||||||
$("search").onclick = e => lsp.openSearchPanel(view);
|
$("search").onclick = e => lsp.openSearchPanel(view);
|
||||||
|
|
||||||
$("fullscreen").onclick = e => $("editor").requestFullscreen();
|
$("fullscreen").onclick = e => $("editor").requestFullscreen();
|
||||||
|
|
||||||
$("bnWordAt").onclick = e => {
|
$("bnWordAt").onclick = e => {
|
||||||
let pos = view.state.selection.main.head;
|
let pos = view.state.selection.main.head;
|
||||||
let w = view.state.wordAt(pos);
|
let w = view.state.wordAt(pos);
|
||||||
alert("wordAt " + JSON.stringify(w));
|
alert("wordAt " + JSON.stringify(w));
|
||||||
};
|
};
|
||||||
|
|
||||||
$("symbols2").onclick = e => {
|
$("symbols2").onclick = e => {
|
||||||
client.sync();
|
client.sync();
|
||||||
client.request("textDocument/documentSymbol", { "textDocument": { "uri": $("iFile").value } })
|
client.request("textDocument/documentSymbol", { "textDocument": { "uri": $("iFile").value } })
|
||||||
.then(r => {
|
.then(r => {
|
||||||
console.log("symbols", r)
|
console.log("symbols", r)
|
||||||
$("symPanel").open = true;
|
$("symPanel").open = true;
|
||||||
$("symList").setData(r);
|
$("symList").setData(r);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$("cmdList").onclick = e => {
|
$("cmdList").onclick = e => {
|
||||||
let cmds = lsp.listCommands(view);
|
let cmds = lsp.listCommands(view);
|
||||||
let result = "";
|
let result = "";
|
||||||
[...cmds.keys()].sort().forEach(key => {
|
[...cmds.keys()].sort().forEach(key => {
|
||||||
result += `<li>${key} ${cmds.get(key).key}</li>`
|
result += `<li>${key} ${cmds.get(key).key}</li>`
|
||||||
});
|
});
|
||||||
$("popHelpInfo").innerHTML = `<ul>${result}</ul>`
|
$("popHelpInfo").innerHTML = `<ul>${result}</ul>`
|
||||||
$("popCmds").showPopover()
|
$("popCmds").showPopover()
|
||||||
};
|
};
|
||||||
|
|
||||||
$("symList").addEventListener("itemSelected", e => {
|
$("symList").addEventListener("itemSelected", e => {
|
||||||
const plugin = lsp.LSPPlugin.get(view)
|
const plugin = lsp.LSPPlugin.get(view)
|
||||||
if (!plugin) return;
|
if (!plugin) return;
|
||||||
const sel = e.detail.range // or selectionRange;
|
const sel = e.detail.range // or selectionRange;
|
||||||
console.log("SYM selection range", sel);
|
console.log("SYM selection range", sel);
|
||||||
const an = plugin.fromPosition(sel.start)
|
const an = plugin.fromPosition(sel.start)
|
||||||
const hd = plugin.fromPosition(sel.end)
|
const hd = plugin.fromPosition(sel.end)
|
||||||
view.dispatch({ selection: { anchor: an, head: hd }, scrollIntoView: true });
|
view.dispatch({ selection: { anchor: an, head: hd }, scrollIntoView: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
$("lint").onclick = async e => {
|
$("lint").onclick = async e => {
|
||||||
console.log("word", view.state.wordAt(1));
|
console.log("word", view.state.wordAt(1));
|
||||||
lsp.openLintPanel(view);
|
lsp.openLintPanel(view);
|
||||||
};
|
};
|
||||||
|
|
||||||
$("sync").onclick = e => { client.sync(); console.log("XXXsync"); };
|
$("sync").onclick = e => { client.sync(); console.log("XXXsync"); };
|
||||||
// state a state
|
// state a state
|
||||||
$("bnSave").onclick = e => { workspace[iFile] = view.state; };
|
$("bnSave").onclick = e => { workspace[iFile] = view.state; };
|
||||||
$("bnLoad").onclick = e => { const v = workspace[iFile]; if (v) view.setState(v) };
|
$("bnLoad").onclick = e => { const v = workspace[iFile]; if (v) view.setState(v) };
|
||||||
|
|
||||||
|
|
||||||
// select local file
|
// select local file
|
||||||
$("bnRead").onclick = e => { $("fileElem").click(); };
|
$("bnRead").onclick = e => { $("fileElem").click(); };
|
||||||
$("fileElem").onchange = e => {
|
$("fileElem").onchange = e => {
|
||||||
let file = e.target.files[0]
|
let file = e.target.files[0]
|
||||||
let fr = new FileReader();
|
let fr = new FileReader();
|
||||||
fr.onload = () => docSwitch(fr.result, file.name);
|
fr.onload = () => docSwitch(fr.result, file.name);
|
||||||
fr.readAsText(file);
|
fr.readAsText(file);
|
||||||
};
|
};
|
||||||
|
|
||||||
$("format").onclick = e => { console.log("FMT", lsp.formatDocument(view)); };
|
$("format").onclick = e => { console.log("FMT", lsp.formatDocument(view)); };
|
||||||
|
|
||||||
$("popUrl").onsubmit = e => {
|
$("popUrl").onsubmit = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const f = objectFromForm("popUrl");
|
const f = objectFromForm("popUrl");
|
||||||
fetch(f.url)
|
fetch(f.url)
|
||||||
.then(response => response.text())
|
.then(response => response.text())
|
||||||
.then(t => {
|
.then(t => {
|
||||||
docSwitch(t, f.url)
|
docSwitch(t, f.url)
|
||||||
$("popWeb").open = false;
|
$("popWeb").open = false;
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
alert("CORS?: " + error)
|
alert("CORS?: " + error)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
$("bnDebug").onclick = e => { debugger; };
|
$("bnDebug").onclick = e => { debugger; };
|
||||||
|
|
||||||
|
|
||||||
$("tConnect").addEventListener('quiet-change', e => {
|
$("tConnect").addEventListener('quiet-change', e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$("popConnect").showPopover()
|
$("popConnect").showPopover()
|
||||||
});
|
});
|
||||||
$("msgIcon").onclick = e => {
|
$("msgIcon").onclick = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
alert("NOT YET")
|
alert("NOT YET")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function updateSettings(event) {
|
function updateSettings(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
console.log("COPTS", lsp.curOpts);
|
console.log("COPTS", lsp.curOpts);
|
||||||
const opts = {
|
const opts = {
|
||||||
lineWrap: $("lineWrap").checked,
|
lineWrap: $("lineWrap").checked,
|
||||||
highlightWhitespace: $("highlightWhitespace").checked,
|
highlightWhitespace: $("highlightWhitespace").checked,
|
||||||
minimap: $("minimap").checked
|
minimap: $("minimap").checked
|
||||||
}
|
}
|
||||||
console.log(opts)
|
console.log(opts)
|
||||||
lsp.updateCompartment(opts);
|
lsp.updateCompartment(opts);
|
||||||
$('popSettings').hidePopover();
|
$('popSettings').hidePopover();
|
||||||
formToStore("fSettings");
|
formToStore("fSettings");
|
||||||
};
|
};
|
||||||
|
|
||||||
$("fSettings").addEventListener("submit", updateSettings);
|
$("fSettings").addEventListener("submit", updateSettings);
|
||||||
|
|
||||||
function connect() {
|
function connect() {
|
||||||
const server = $("iServer").value;
|
const server = $("iServer").value;
|
||||||
const file = $("iFile").value;
|
const file = $("iFile").value;
|
||||||
lsp.simpleWebSocketTransport(server)
|
lsp.simpleWebSocketTransport(server)
|
||||||
.then(transport => {
|
.then(transport => {
|
||||||
transport.socket.onclose = (event) => $("tConnect").checked = false;
|
transport.socket.onclose = (event) => $("tConnect").checked = false;
|
||||||
transport.socket.oneror = (event) => $("msg").innerText = "sock error!";
|
transport.socket.oneror = (event) => $("msg").innerText = "sock error!";
|
||||||
transport.subscribe(incoming);
|
transport.subscribe(incoming);
|
||||||
client = new lsp.LSPClient({ extensions: lsp.languageServerExtensions() });
|
client = new lsp.LSPClient({ extensions: lsp.languageServerExtensions() });
|
||||||
client.connect(transport);
|
client.connect(transport);
|
||||||
$("popConnect").hidePopover();
|
$("popConnect").hidePopover();
|
||||||
$("tConnect").checked = true;
|
$("tConnect").checked = true;
|
||||||
$("tipConnect").innerText=server;
|
$("tipConnect").innerText=server;
|
||||||
const extLsp = client.plugin(file, "xquery");
|
const extLsp = client.plugin(file, "xquery");
|
||||||
|
|
||||||
view.dispatch({
|
view.dispatch({
|
||||||
effects: lsp.StateEffect.appendConfig.of(
|
effects: lsp.StateEffect.appendConfig.of(
|
||||||
[lsp.linter(null, { autoPanel: true }), ...extLsp,
|
[lsp.linter(null, { autoPanel: true }), ...extLsp,
|
||||||
lsp.keymap.of([...lsp.formatKeymap])])
|
lsp.keymap.of([...lsp.formatKeymap])])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
$("tConnect").checked = false;
|
$("tConnect").checked = false;
|
||||||
alert("connection failed: " + server)
|
alert("connection failed: " + server)
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// change active doc
|
// change active doc
|
||||||
function docSwitch(text,urlNew) {
|
function docSwitch(text,urlNew) {
|
||||||
const urlOld=$("iFile").value;
|
const urlOld=$("iFile").value;
|
||||||
client.workspace.closeFile(urlOld);
|
client.workspace.closeFile(urlOld);
|
||||||
view.dispatch({
|
view.dispatch({
|
||||||
changes: {
|
changes: {
|
||||||
from: 0,
|
from: 0,
|
||||||
to: view.state.doc.length,
|
to: view.state.doc.length,
|
||||||
insert: text
|
insert: text
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
client.workspace.openFile(urlNew,"xquery",view)
|
client.workspace.openFile(urlNew,"xquery",view)
|
||||||
$("iFile").value = urlNew;
|
$("iFile").value = urlNew;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function incoming(msg) {
|
function incoming(msg) {
|
||||||
const rpc = JSON.parse(msg);
|
const rpc = JSON.parse(msg);
|
||||||
log(rpc);
|
log(rpc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function log(rpc) {
|
function log(rpc) {
|
||||||
console.log("<-", rpc)
|
console.log("<-", rpc)
|
||||||
const when = (new Date()).toISOString();
|
const when = (new Date()).toISOString();
|
||||||
const msg = { name: rpc.method ?? rpc.id, detail: when.substring(1 + when.indexOf("T")), kind: 23 /* event */ };
|
const msg = { name: rpc.method ?? rpc.id, detail: when.substring(1 + when.indexOf("T")), kind: 23 /* event */ };
|
||||||
//name,details,kind
|
//name,details,kind
|
||||||
$("msgList").setData([msg], true)
|
$("msgList").setData([msg], true)
|
||||||
$("relative-time__live").date=new Date();
|
$("relative-time__live").date=new Date();
|
||||||
};
|
};
|
||||||
|
|
||||||
function formFromStore(name) {
|
function formFromStore(name) {
|
||||||
let v = localStorage.getItem(name)
|
let v = localStorage.getItem(name)
|
||||||
if (!!v) formDeserialize($(name), v);
|
if (!!v) formDeserialize($(name), v);
|
||||||
};
|
};
|
||||||
|
|
||||||
function formToStore(name) {
|
function formToStore(name) {
|
||||||
localStorage.setItem(name, formSerialize($(name)));
|
localStorage.setItem(name, formSerialize($(name)));
|
||||||
};
|
};
|
||||||
|
|
||||||
function objectFromForm(name) {
|
function objectFromForm(name) {
|
||||||
const data = new FormData($(name));
|
const data = new FormData($(name));
|
||||||
//https://stackabuse.com/convert-form-data-to-javascript-object/
|
//https://stackabuse.com/convert-form-data-to-javascript-object/
|
||||||
return Object.fromEntries(data.entries());
|
return Object.fromEntries(data.entries());
|
||||||
}
|
}
|
||||||
function formSerialize(form) {
|
function formSerialize(form) {
|
||||||
const data = new FormData(form);
|
const data = new FormData(form);
|
||||||
//https://stackoverflow.com/a/44033425/1869660
|
//https://stackoverflow.com/a/44033425/1869660
|
||||||
return new URLSearchParams(data).toString();
|
return new URLSearchParams(data).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
function formDeserialize(form, data) {
|
function formDeserialize(form, data) {
|
||||||
const entries = (new URLSearchParams(data)).entries();
|
const entries = (new URLSearchParams(data)).entries();
|
||||||
for (const [key, val] of entries) {
|
for (const [key, val] of entries) {
|
||||||
//http://javascript-coder.com/javascript-form/javascript-form-value.phtml
|
//http://javascript-coder.com/javascript-form/javascript-form-value.phtml
|
||||||
const input = form.elements[key];
|
const input = form.elements[key];
|
||||||
switch (input.type) {
|
switch (input.type) {
|
||||||
case 'checkbox': input.checked = !!val; break;
|
case 'checkbox': input.checked = !!val; break;
|
||||||
default: input.value = val; break;
|
default: input.value = val; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,35 +1,35 @@
|
||||||
|
|
||||||
@import url("../bootstrap-icons.min.css");
|
@import url("../bootstrap-icons.min.css");
|
||||||
html { height: 100%;}
|
html { height: 100%;}
|
||||||
body { min-height: 100vh; }
|
body { min-height: 100vh; }
|
||||||
|
|
||||||
/* Set editor dimensions */
|
/* Set editor dimensions */
|
||||||
#editor {
|
#editor {
|
||||||
height: 400px;
|
height: 400px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: burlywood;
|
background-color: burlywood;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stretch editor to fit inside its containing div */
|
/* Stretch editor to fit inside its containing div */
|
||||||
.cm-editor {
|
.cm-editor {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/* header */
|
/* header */
|
||||||
nav {
|
nav {
|
||||||
background-color: burlywood!;
|
background-color: burlywood!;
|
||||||
}
|
}
|
||||||
.nav-pills > li > a
|
.nav-pills > li > a
|
||||||
{
|
{
|
||||||
/* adjust padding for height*/
|
/* adjust padding for height*/
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
}
|
}
|
||||||
dialog > header
|
dialog > header
|
||||||
{
|
{
|
||||||
background-color: burlywood;
|
background-color: burlywood;
|
||||||
}
|
}
|
||||||
|
|
@ -1,204 +1,204 @@
|
||||||
/* Define a web component providing a settable and selectable list
|
/* Define a web component providing a settable and selectable list
|
||||||
$("symList").setData(r, append = false);
|
$("symList").setData(r, append = false);
|
||||||
where r is array of objects with properties name,detail,kind
|
where r is array of objects with properties name,detail,kind
|
||||||
|
|
||||||
https://stackoverflow.com/questions/50404970/web-components-pass-data-to-and-from
|
https://stackoverflow.com/questions/50404970/web-components-pass-data-to-and-from
|
||||||
https://www.w3schools.com/howto/howto_js_treeview.asp
|
https://www.w3schools.com/howto/howto_js_treeview.asp
|
||||||
*/
|
*/
|
||||||
class ListComponent extends HTMLElement {
|
class ListComponent extends HTMLElement {
|
||||||
#shadow;
|
#shadow;
|
||||||
#data;
|
#data;
|
||||||
#iconKinds; //array from kind integer to codicon name
|
#iconKinds; //array from kind integer to codicon name
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.#shadow = this.attachShadow({ mode: "open", delegatesFocus: true });
|
this.#shadow = this.attachShadow({ mode: "open", delegatesFocus: true });
|
||||||
this.#data = [];
|
this.#data = [];
|
||||||
// codicons kind
|
// codicons kind
|
||||||
this.#iconKinds = [
|
this.#iconKinds = [
|
||||||
'symbol-file',
|
'symbol-file',
|
||||||
'symbol-class',
|
'symbol-class',
|
||||||
'symbol-namespace',
|
'symbol-namespace',
|
||||||
'symbol-structure',
|
'symbol-structure',
|
||||||
'symbol-class',
|
'symbol-class',
|
||||||
'symbol-method',
|
'symbol-method',
|
||||||
'symbol-property',
|
'symbol-property',
|
||||||
'symbol-field',
|
'symbol-field',
|
||||||
'symbol-method-arrow',
|
'symbol-method-arrow',
|
||||||
'symbol-enum',
|
'symbol-enum',
|
||||||
'symbol-interface',
|
'symbol-interface',
|
||||||
'symbol-method',
|
'symbol-method',
|
||||||
'symbol-variable',
|
'symbol-variable',
|
||||||
'symbol-constant',
|
'symbol-constant',
|
||||||
'symbol-string',
|
'symbol-string',
|
||||||
'symbol-numeric',
|
'symbol-numeric',
|
||||||
'symbol-boolean',
|
'symbol-boolean',
|
||||||
'symbol-array',
|
'symbol-array',
|
||||||
'symbol-structure',
|
'symbol-structure',
|
||||||
'symbol-key',
|
'symbol-key',
|
||||||
'dash',
|
'dash',
|
||||||
'symbol-enum-member',
|
'symbol-enum-member',
|
||||||
'symbol-misc',
|
'symbol-misc',
|
||||||
'symbol-event',
|
'symbol-event',
|
||||||
'symbol-operator',
|
'symbol-operator',
|
||||||
'symbol-parameter'
|
'symbol-parameter'
|
||||||
];
|
];
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
setData(newData, append = false) {
|
setData(newData, append = false) {
|
||||||
if (!Array.isArray(newData)) {
|
if (!Array.isArray(newData)) {
|
||||||
console.warn("Invalid format, expected an array.");
|
console.warn("Invalid format, expected an array.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#data = append ? this.#data.concat(newData) : structuredClone(newData);
|
this.#data = append ? this.#data.concat(newData) : structuredClone(newData);
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
set data(value) {
|
set data(value) {
|
||||||
this.setData(value, false);
|
this.setData(value, false);
|
||||||
}
|
}
|
||||||
get data() {
|
get data() {
|
||||||
return this.#data;
|
return this.#data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render the list items #data */
|
/* Render the list items #data */
|
||||||
render() {
|
render() {
|
||||||
// eventhandler for click and keyboard, updates usage of selected class and raises event
|
// eventhandler for click and keyboard, updates usage of selected class and raises event
|
||||||
const select = e => {
|
const select = e => {
|
||||||
if(e.type ==="keyup" && !(e.key==="Enter" )) return;
|
if(e.type ==="keyup" && !(e.key==="Enter" )) return;
|
||||||
this.#shadow.querySelectorAll('li.selected').forEach(item => { item.className = ''; });
|
this.#shadow.querySelectorAll('li.selected').forEach(item => { item.className = ''; });
|
||||||
e.currentTarget.className = 'selected';
|
e.currentTarget.className = 'selected';
|
||||||
const i=e.currentTarget.getAttribute("data-index")
|
const i=e.currentTarget.getAttribute("data-index")
|
||||||
console.log('Item index clicked:', i,this.#data[i]);
|
console.log('Item index clicked:', i,this.#data[i]);
|
||||||
// You can dispatch a custom event here if needed.
|
// You can dispatch a custom event here if needed.
|
||||||
this.dispatchEvent(new CustomEvent('itemSelected', {
|
this.dispatchEvent(new CustomEvent('itemSelected', {
|
||||||
detail: this.#data[i],
|
detail: this.#data[i],
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
composed: true
|
composed: true
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
// create list and items
|
// create list and items
|
||||||
const list = document.createElement('ul');
|
const list = document.createElement('ul');
|
||||||
list.style = "overflow: auto;";
|
list.style = "overflow: auto;";
|
||||||
this.#data.forEach((item, index) => {
|
this.#data.forEach((item, index) => {
|
||||||
const listItem = document.createElement('li');
|
const listItem = document.createElement('li');
|
||||||
const icon=this.#iconKinds[item.kind];
|
const icon=this.#iconKinds[item.kind];
|
||||||
listItem.setAttribute("tabindex", "0")
|
listItem.setAttribute("tabindex", "0")
|
||||||
listItem.setAttribute("data-index", index)
|
listItem.setAttribute("data-index", index)
|
||||||
listItem.innerHTML = `<i class='codicon codicon-${icon}'
|
listItem.innerHTML = `<i class='codicon codicon-${icon}'
|
||||||
title='${icon}'></i>
|
title='${icon}'></i>
|
||||||
<span >${item.name} - ${item.detail}</span>`;
|
<span >${item.name} - ${item.detail}</span>`;
|
||||||
|
|
||||||
listItem.addEventListener('click', select);
|
listItem.addEventListener('click', select);
|
||||||
listItem.addEventListener('keyup', select);
|
listItem.addEventListener('keyup', select);
|
||||||
list.appendChild(listItem);
|
list.appendChild(listItem);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.#shadow.innerHTML = '';
|
this.#shadow.innerHTML = '';
|
||||||
const style = document.createElement('style');
|
const style = document.createElement('style');
|
||||||
style.textContent = `
|
style.textContent = `
|
||||||
@import url("../codicon@0.0.40/codicon.css");
|
@import url("../codicon@0.0.40/codicon.css");
|
||||||
ul { list-style-type: none; padding:0;margin:0;overflow: auto;
|
ul { list-style-type: none; padding:0;margin:0;overflow: auto;
|
||||||
background-color: #f8f9fa;font-size: 80%;}
|
background-color: #f8f9fa;font-size: 80%;}
|
||||||
li { padding: 0 0 0 2px; cursor: pointer; width:100%; }
|
li { padding: 0 0 0 2px; cursor: pointer; width:100%; }
|
||||||
li:not(.selected) :hover { background-color: #ccc; }
|
li:not(.selected) :hover { background-color: #ccc; }
|
||||||
.selected { background-color: #0d6efd;color: #ffff;}
|
.selected { background-color: #0d6efd;color: #ffff;}
|
||||||
i {vertical-align: middle;}
|
i {vertical-align: middle;}
|
||||||
`;
|
`;
|
||||||
this.#shadow.appendChild(style);
|
this.#shadow.appendChild(style);
|
||||||
this.#shadow.appendChild(list);
|
this.#shadow.appendChild(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render an error message if JSON fetching fails */
|
/* Render an error message if JSON fetching fails */
|
||||||
renderError(error) {
|
renderError(error) {
|
||||||
this.#shadow.innerHTML = `<p>Error loading data: ${error.message}</p>`;
|
this.#shadow.innerHTML = `<p>Error loading data: ${error.message}</p>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Define the new custom element */
|
/* Define the new custom element */
|
||||||
customElements.define('qd-list', ListComponent);
|
customElements.define('qd-list', ListComponent);
|
||||||
|
|
||||||
class PanelComponent extends HTMLElement {
|
class PanelComponent extends HTMLElement {
|
||||||
#shadow;
|
#shadow;
|
||||||
#data;
|
#data;
|
||||||
#iconKinds; //array from kind integer to codicon name
|
#iconKinds; //array from kind integer to codicon name
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.#shadow = this.attachShadow({ mode: "open", delegatesFocus: true });
|
this.#shadow = this.attachShadow({ mode: "open", delegatesFocus: true });
|
||||||
this.#data = [];
|
this.#data = [];
|
||||||
this.#iconKinds = [];
|
this.#iconKinds = [];
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
setData(newData, append = false) {
|
setData(newData, append = false) {
|
||||||
if (!Array.isArray(newData)) {
|
if (!Array.isArray(newData)) {
|
||||||
console.warn("Invalid format, expected an array.");
|
console.warn("Invalid format, expected an array.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.#data = append ? this.#data.concat(newData) : structuredClone(newData);
|
this.#data = append ? this.#data.concat(newData) : structuredClone(newData);
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
set data(value) {
|
set data(value) {
|
||||||
this.setData(value, false);
|
this.setData(value, false);
|
||||||
}
|
}
|
||||||
get data() {
|
get data() {
|
||||||
return this.#data;
|
return this.#data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render the list items #data */
|
/* Render the list items #data */
|
||||||
render() {
|
render() {
|
||||||
const list = document.createElement('ul');
|
const list = document.createElement('ul');
|
||||||
list.style = "overflow: auto;";
|
list.style = "overflow: auto;";
|
||||||
|
|
||||||
const select = e => {
|
const select = e => {
|
||||||
if(e.type ==="keyup" && !(e.key==="Enter" )) return;
|
if(e.type ==="keyup" && !(e.key==="Enter" )) return;
|
||||||
this.#shadow.querySelectorAll('li.selected').forEach(item => { item.className = ''; });
|
this.#shadow.querySelectorAll('li.selected').forEach(item => { item.className = ''; });
|
||||||
e.currentTarget.className = 'selected';
|
e.currentTarget.className = 'selected';
|
||||||
const i=e.currentTarget.getAttribute("data-index")
|
const i=e.currentTarget.getAttribute("data-index")
|
||||||
console.log('Item index clicked:', i,this.#data[i]);
|
console.log('Item index clicked:', i,this.#data[i]);
|
||||||
// You can dispatch a custom event here if needed.
|
// You can dispatch a custom event here if needed.
|
||||||
this.dispatchEvent(new CustomEvent('itemSelected', {
|
this.dispatchEvent(new CustomEvent('itemSelected', {
|
||||||
detail: this.#data[i],
|
detail: this.#data[i],
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
composed: true
|
composed: true
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
this.#data.forEach((item, index) => {
|
this.#data.forEach((item, index) => {
|
||||||
const listItem = document.createElement('li');
|
const listItem = document.createElement('li');
|
||||||
const icon=this.#iconKinds[item.kind];
|
const icon=this.#iconKinds[item.kind];
|
||||||
listItem.setAttribute("tabindex", "0")
|
listItem.setAttribute("tabindex", "0")
|
||||||
listItem.setAttribute("data-index", index)
|
listItem.setAttribute("data-index", index)
|
||||||
listItem.innerHTML = `<span title='A ${icon}'>XX<i class='codicon codicon-${icon}' >*</i></span>
|
listItem.innerHTML = `<span title='A ${icon}'>XX<i class='codicon codicon-${icon}' >*</i></span>
|
||||||
<span >${item.name} - ${item.detail}</span>`;
|
<span >${item.name} - ${item.detail}</span>`;
|
||||||
|
|
||||||
listItem.addEventListener('click', select);
|
listItem.addEventListener('click', select);
|
||||||
listItem.addEventListener('keyup', select);
|
listItem.addEventListener('keyup', select);
|
||||||
list.appendChild(listItem);
|
list.appendChild(listItem);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.#shadow.innerHTML = '';
|
this.#shadow.innerHTML = '';
|
||||||
const style = document.createElement('style');
|
const style = document.createElement('style');
|
||||||
style.textContent = `
|
style.textContent = `
|
||||||
@import url("../codicon@0.0.40/codicon.css");
|
@import url("../codicon@0.0.40/codicon.css");
|
||||||
ul { list-style-type: none; padding:0;margin:0;
|
ul { list-style-type: none; padding:0;margin:0;
|
||||||
background-color: #e3e4e4ff;font-size: 80%; scrollbar-color: #000077 #bada55;}
|
background-color: #e3e4e4ff;font-size: 80%; scrollbar-color: #000077 #bada55;}
|
||||||
li { padding: 0 0 0 2px; border-bottom: 1px solid #ccc; cursor: pointer; width:100%; }
|
li { padding: 0 0 0 2px; border-bottom: 1px solid #ccc; cursor: pointer; width:100%; }
|
||||||
li:not(.selected) :hover { background-color: #ccc; }
|
li:not(.selected) :hover { background-color: #ccc; }
|
||||||
.selected { background-color: #0d6efd;color: #ffff;}
|
.selected { background-color: #0d6efd;color: #ffff;}
|
||||||
i {vertical-align: middle;}
|
i {vertical-align: middle;}
|
||||||
`;
|
`;
|
||||||
this.#shadow.appendChild(style);
|
this.#shadow.appendChild(style);
|
||||||
this.#shadow.appendChild(list);
|
this.#shadow.appendChild(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render an error message if JSON fetching fails */
|
/* Render an error message if JSON fetching fails */
|
||||||
renderError(error) {
|
renderError(error) {
|
||||||
this.#shadow.innerHTML = `<p>Error loading data: ${error.message}</p>`;
|
this.#shadow.innerHTML = `<p>Error loading data: ${error.message}</p>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Define the new custom element */
|
/* Define the new custom element */
|
||||||
customElements.define('qd-panel', PanelComponent);
|
customElements.define('qd-panel', PanelComponent);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,33 @@
|
||||||
// a popover dialog NOT WORKING
|
// a popover dialog NOT WORKING
|
||||||
class PopupInfo extends HTMLElement {
|
class PopupInfo extends HTMLElement {
|
||||||
constructor() {
|
constructor() {
|
||||||
// Always call super first in constructor
|
// Always call super first in constructor
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
// Create a shadow root
|
// Create a shadow root
|
||||||
const shadow = this.attachShadow({ mode: "open" });
|
const shadow = this.attachShadow({ mode: "open" });
|
||||||
|
|
||||||
// Create spans
|
// Create spans
|
||||||
const dialog = document.createElement("dialog");
|
const dialog = document.createElement("dialog");
|
||||||
dialog.setAttribute("id", this.getAttribute("id"));
|
dialog.setAttribute("id", this.getAttribute("id"));
|
||||||
dialog.setAttribute("popover","popover");
|
dialog.setAttribute("popover","popover");
|
||||||
const header = document.createElement("header");
|
const header = document.createElement("header");
|
||||||
header.innerText="HEADE"
|
header.innerText="HEADE"
|
||||||
const main = document.createElement("main");
|
const main = document.createElement("main");
|
||||||
main.innerText="MAIN"
|
main.innerText="MAIN"
|
||||||
const footer = document.createElement("footer");
|
const footer = document.createElement("footer");
|
||||||
footer.innerText="WWW"
|
footer.innerText="WWW"
|
||||||
dialog.appendChild(header);
|
dialog.appendChild(header);
|
||||||
dialog.appendChild(main);
|
dialog.appendChild(main);
|
||||||
dialog.appendChild(footer)
|
dialog.appendChild(footer)
|
||||||
// Attach the created elements to the shadow dom
|
// Attach the created elements to the shadow dom
|
||||||
shadow.appendChild(dialog);
|
shadow.appendChild(dialog);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define the new element
|
// Define the new element
|
||||||
customElements.define("popup-info", PopupInfo);
|
customElements.define("popup-info", PopupInfo);
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
```html
|
```html
|
||||||
<i class='codicon codicon-symbol-method'></i>
|
<i class='codicon codicon-symbol-method'></i>
|
||||||
```
|
```
|
||||||
|
|
||||||
* [search codicon icons](https://microsoft.github.io/vscode-codicons/dist/codicon.html)
|
* [search codicon icons](https://microsoft.github.io/vscode-codicons/dist/codicon.html)
|
||||||
* https://github.com/microsoft/vscode-codicons
|
* https://github.com/microsoft/vscode-codicons
|
||||||
* https://github.com/microsoft/vscode-codicons/releases/tag/v0.0.40
|
* https://github.com/microsoft/vscode-codicons/releases/tag/v0.0.40
|
||||||
Loading…
Add table
Reference in a new issue