jupyterlab_code_formatter 2.2.1 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,31 +1,36 @@
1
1
  ![](docs/logo.png)
2
2
 
3
- *A JupyterLab plugin to facilitate invocation of code formatters.*
3
+ [![Extension status](https://img.shields.io/badge/status-ready-success 'ready to be used')](https://jupyterlab-contrib.github.io/)
4
+ [![GitHub Action Status](https://github.com/jupyterlab-contrib/jupyterlab_code_formatter/actions/workflows/build.yml/badge.svg)](https://github.com/jupyterlab-contrib/jupyterlab_code_formatter/actions/workflows/build.yml)
5
+ [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/jupyterlab-contrib/jupyterlab_code_formatter/master?urlpath=lab)
6
+ [![pypi-version](https://img.shields.io/pypi/v/jupyterlab-code-formatter.svg)](https://python.org/pypi/jupyterlab-code-formatter)
4
7
 
5
- PSA: I can only dedicate a few hours per week for this plugin, bear with me if your request/issue is taking a while to be fixed.
8
+ _A JupyterLab plugin to facilitate invocation of code formatters._
6
9
 
7
- ----
10
+ ---
8
11
 
9
12
  Documentation: [Hosted on ReadTheDocs](https://jupyterlab-code-formatter.readthedocs.io/)
10
13
 
11
- ----
14
+ ---
12
15
 
13
16
  ## Demo
14
17
 
15
18
  ![](docs/_static/format-all.gif)
16
19
 
17
- ----
20
+ ---
18
21
 
19
22
  ## Quick Start
20
23
 
21
24
  I recommend you going to the [documentation site](https://jupyterlab-code-formatter.readthedocs.io/#quick-start), but this should work too.
22
25
 
23
26
  1. **Install the package**
27
+
24
28
  ```bash
25
29
  pip install jupyterlab-code-formatter
26
30
  ```
27
31
 
28
32
  2. **Install some supported formatters** (isort+black are default for Python)
33
+
29
34
  ```bash
30
35
  # NOTE: Install black and isort,
31
36
  # JL code formatter is configured to invoke isort and black by default
@@ -40,25 +45,30 @@ This plugin includes a server plugin, restart JupyterLab if you have followed th
40
45
 
41
46
  To configure which/how formatters are invoked, see [configuration](https://jupyterlab-code-formatter.readthedocs.io/configuration.html).
42
47
 
43
- ----
48
+ ---
49
+
50
+ ## Getting help
51
+
52
+ If you don't use Discord then feel free to open a [GitHub issue](https://github.com/jupyterlab-contrib/jupyterlab_code_formatter/issues), do note I am a bit slower in responding in GitHub.
53
+
54
+ ---
44
55
 
45
56
  ## Your Support
46
57
 
47
- I could really use your support in giving me a star on GitHub, recommending features, fixing bugs or maybe even providing monetary support!
58
+ I could really use your support in giving me a star on GitHub, recommending features or fixing bugs.
48
59
 
49
- - [Recommending features via GitHub Issues](https://github.com/ryantam626/jupyterlab_code_formatter/issues)
50
- - [Sumitting your PR on GitHub](https://github.com/ryantam626/jupyterlab_code_formatter/pulls)
51
- - [Buy me a coffee](https://www.buymeacoffee.com/ryantam626)
52
- - [Donating Via Solana](https://solana.com/): 6K7aK5RpskJkhEkwZi1ZQr68LhaVdfnTfWjZEQV3VbbD
60
+ - [Recommending features via GitHub Issues](https://github.com/jupyterlab-contrib/jupyterlab_code_formatter/issues)
61
+ - [Submitting your PR on GitHub](https://github.com/jupyterlab-contrib/jupyterlab_code_formatter/pulls)
53
62
 
54
- ----
63
+ ---
55
64
 
56
65
  ## Contributors
57
66
 
67
+ This extension was originally developed and maintained by [@ryantam626](https://github.com/ryantam626).
58
68
  Massive thanks to the below list of people who made past contributions to the project!
59
69
 
60
- <a href="https://github.com/ryantam626/jupyterlab_code_formatter/graphs/contributors">
61
- <img src="https://contrib.rocks/image?repo=ryantam626/jupyterlab_code_formatter" />
70
+ <a href="https://github.com/jupyterlab-contrib/jupyterlab_code_formatter/graphs/contributors">
71
+ <img src="https://contrib.rocks/image?repo=jupyterlab-contrib/jupyterlab_code_formatter" />
62
72
  </a>
63
73
 
64
74
  ## License
@@ -2,6 +2,9 @@ import { INotebookTracker, Notebook } from '@jupyterlab/notebook';
2
2
  import JupyterlabCodeFormatterClient from './client';
3
3
  import { IEditorTracker } from '@jupyterlab/fileeditor';
4
4
  import { Widget } from '@lumino/widgets';
5
+ type Context = {
6
+ saving: boolean;
7
+ };
5
8
  declare class JupyterlabCodeFormatter {
6
9
  working: boolean;
7
10
  protected client: JupyterlabCodeFormatterClient;
@@ -13,7 +16,7 @@ export declare class JupyterlabNotebookCodeFormatter extends JupyterlabCodeForma
13
16
  constructor(client: JupyterlabCodeFormatterClient, notebookTracker: INotebookTracker);
14
17
  formatAction(config: any, formatter?: string): Promise<void>;
15
18
  formatSelectedCodeCells(config: any, formatter?: string, notebook?: Notebook): Promise<void>;
16
- formatAllCodeCells(config: any, formatter?: string, notebook?: Notebook): Promise<void>;
19
+ formatAllCodeCells(config: any, context: Context, formatter?: string, notebook?: Notebook): Promise<void>;
17
20
  private getCodeCells;
18
21
  private getNotebookType;
19
22
  private getDefaultFormatters;
@@ -25,7 +28,12 @@ export declare class JupyterlabNotebookCodeFormatter extends JupyterlabCodeForma
25
28
  export declare class JupyterlabFileEditorCodeFormatter extends JupyterlabCodeFormatter {
26
29
  protected editorTracker: IEditorTracker;
27
30
  constructor(client: JupyterlabCodeFormatterClient, editorTracker: IEditorTracker);
28
- formatAction(config: any, formatter: string): void;
31
+ formatAction(config: any, formatter: string): Promise<void>;
32
+ formatEditor(config: any, context: Context, formatter?: string): Promise<void>;
33
+ private getEditorType;
34
+ private getDefaultFormatters;
35
+ private getFormattersToUse;
36
+ private applyFormatters;
29
37
  applicable(formatter: string, currentWidget: Widget): boolean | null;
30
38
  }
31
39
  export {};
package/lib/formatter.js CHANGED
@@ -1,4 +1,4 @@
1
- import { showErrorMessage } from '@jupyterlab/apputils';
1
+ import { showErrorMessage, Dialog, showDialog } from '@jupyterlab/apputils';
2
2
  class JupyterlabCodeFormatter {
3
3
  constructor(client) {
4
4
  this.working = false;
@@ -21,13 +21,13 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter {
21
21
  this.notebookTracker = notebookTracker;
22
22
  }
23
23
  async formatAction(config, formatter) {
24
- return this.formatCells(true, config, formatter);
24
+ return this.formatCells(true, config, { saving: false }, formatter);
25
25
  }
26
26
  async formatSelectedCodeCells(config, formatter, notebook) {
27
- return this.formatCells(true, config, formatter, notebook);
27
+ return this.formatCells(true, config, { saving: false }, formatter, notebook);
28
28
  }
29
- async formatAllCodeCells(config, formatter, notebook) {
30
- return this.formatCells(false, config, formatter, notebook);
29
+ async formatAllCodeCells(config, context, formatter, notebook) {
30
+ return this.formatCells(false, config, context, formatter, notebook);
31
31
  }
32
32
  getCodeCells(selectedOnly = true, notebook) {
33
33
  if (!this.notebookTracker.currentWidget) {
@@ -49,21 +49,24 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter {
49
49
  return null;
50
50
  }
51
51
  const metadata = this.notebookTracker.currentWidget.content.model.sharedModel.metadata;
52
- ;
53
52
  if (!metadata) {
54
53
  return null;
55
54
  }
56
55
  // prefer kernelspec language
57
- // @ts-ignore
58
- if (metadata.kernelspec && metadata.kernelspec.language) {
59
- // @ts-ignore
56
+ if (metadata.kernelspec &&
57
+ metadata.kernelspec.language &&
58
+ typeof metadata.kernelspec.language === 'string') {
60
59
  return metadata.kernelspec.language.toLowerCase();
61
60
  }
62
61
  // otherwise, check language info code mirror mode
63
- // @ts-ignore
64
62
  if (metadata.language_info && metadata.language_info.codemirror_mode) {
65
- // @ts-ignore
66
- return metadata.language_info.codemirror_mode.name.toLowerCase();
63
+ const mode = metadata.language_info.codemirror_mode;
64
+ if (typeof mode === 'string') {
65
+ return mode.toLowerCase();
66
+ }
67
+ else if (typeof mode.name === 'string') {
68
+ return mode.name.toLowerCase();
69
+ }
67
70
  }
68
71
  return null;
69
72
  }
@@ -88,15 +91,18 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter {
88
91
  }
89
92
  return formattersToUse;
90
93
  }
91
- async applyFormatters(selectedCells, formattersToUse, config) {
92
- var _a;
94
+ async applyFormatters(selectedCells, formattersToUse, config, context) {
95
+ var _a, _b;
93
96
  for (const formatterToUse of formattersToUse) {
94
97
  if (formatterToUse === 'noop' || formatterToUse === 'skip') {
95
98
  continue;
96
99
  }
97
100
  const currentTexts = selectedCells.map(cell => cell.model.sharedModel.source);
98
101
  const formattedTexts = await this.formatCode(currentTexts, formatterToUse, config[formatterToUse], true, config.cacheFormatters);
99
- const showErrors = !((_a = config.suppressFormatterErrors) !== null && _a !== void 0 ? _a : false);
102
+ console.log(config.suppressFormatterErrorsIFFAutoFormatOnSave, context.saving);
103
+ const showErrors = !((_a = config.suppressFormatterErrors) !== null && _a !== void 0 ? _a : false) &&
104
+ !(((_b = config.suppressFormatterErrorsIFFAutoFormatOnSave) !== null && _b !== void 0 ? _b : false) &&
105
+ context.saving);
100
106
  for (let i = 0; i < selectedCells.length; ++i) {
101
107
  const cell = selectedCells[i];
102
108
  const currentText = currentTexts[i];
@@ -105,7 +111,21 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter {
105
111
  if (cellValueHasNotChanged) {
106
112
  if (formattedText.error) {
107
113
  if (showErrors) {
108
- await showErrorMessage('Jupyterlab Code Formatter Error', formattedText.error);
114
+ const result = await showDialog({
115
+ title: 'Jupyterlab Code Formatter Error',
116
+ body: formattedText.error,
117
+ buttons: [
118
+ Dialog.createButton({
119
+ label: 'Go to cell',
120
+ actions: ['revealError']
121
+ }),
122
+ Dialog.okButton({ label: 'Dismiss' })
123
+ ]
124
+ });
125
+ if (result.button.actions.indexOf('revealError') !== -1) {
126
+ this.notebookTracker.currentWidget.content.scrollToCell(cell);
127
+ break;
128
+ }
109
129
  }
110
130
  }
111
131
  else {
@@ -120,7 +140,7 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter {
120
140
  }
121
141
  }
122
142
  }
123
- async formatCells(selectedOnly, config, formatter, notebook) {
143
+ async formatCells(selectedOnly, config, context, formatter, notebook) {
124
144
  if (this.working) {
125
145
  return;
126
146
  }
@@ -132,10 +152,10 @@ export class JupyterlabNotebookCodeFormatter extends JupyterlabCodeFormatter {
132
152
  return;
133
153
  }
134
154
  const formattersToUse = await this.getFormattersToUse(config, formatter);
135
- await this.applyFormatters(selectedCells, formattersToUse, config);
155
+ await this.applyFormatters(selectedCells, formattersToUse, config, context);
136
156
  }
137
157
  catch (error) {
138
- await showErrorMessage('Jupyterlab Code Formatter Error', error);
158
+ await showErrorMessage('Jupyterlab Code Formatter Error', `${error}`);
139
159
  }
140
160
  this.working = false;
141
161
  }
@@ -151,28 +171,90 @@ export class JupyterlabFileEditorCodeFormatter extends JupyterlabCodeFormatter {
151
171
  this.editorTracker = editorTracker;
152
172
  }
153
173
  formatAction(config, formatter) {
174
+ return this.formatEditor(config, { saving: false }, formatter);
175
+ }
176
+ async formatEditor(config, context, formatter) {
154
177
  if (this.working) {
155
178
  return;
156
179
  }
157
- const editorWidget = this.editorTracker.currentWidget;
158
- this.working = true;
159
- const editor = editorWidget.content.editor;
160
- const code = editor.model.sharedModel.source;
161
- this.formatCode([code], formatter, config[formatter], false, config.cacheFormatters)
162
- .then(data => {
163
- if (data.code[0].error) {
164
- void showErrorMessage('Jupyterlab Code Formatter Error', data.code[0].error);
165
- this.working = false;
166
- return;
180
+ try {
181
+ this.working = true;
182
+ const formattersToUse = await this.getFormattersToUse(config, formatter);
183
+ await this.applyFormatters(formattersToUse, config, context);
184
+ }
185
+ catch (error) {
186
+ const msg = error instanceof Error ? error : `${error}`;
187
+ await showErrorMessage('Jupyterlab Code Formatter Error', msg);
188
+ }
189
+ this.working = false;
190
+ }
191
+ getEditorType() {
192
+ if (!this.editorTracker.currentWidget) {
193
+ return null;
194
+ }
195
+ const mimeType = this.editorTracker.currentWidget.content.model.mimeType;
196
+ const mimeTypes = new Map([
197
+ ['text/x-python', 'python'],
198
+ ['application/x-rsrc', 'r'],
199
+ ['application/x-scala', 'scala'],
200
+ ['application/x-rustsrc', 'rust'],
201
+ ['application/x-c++src', 'cpp'] // Not sure that this is right, whatever.
202
+ // Add more MIME types and corresponding programming languages here
203
+ ]);
204
+ return mimeTypes.get(mimeType);
205
+ }
206
+ getDefaultFormatters(config) {
207
+ const editorType = this.getEditorType();
208
+ if (editorType) {
209
+ const defaultFormatter = config.preferences.default_formatter[editorType];
210
+ if (defaultFormatter instanceof Array) {
211
+ return defaultFormatter;
167
212
  }
168
- this.editorTracker.currentWidget.content.editor.model.sharedModel.source =
169
- data.code[0].code;
170
- this.working = false;
171
- })
172
- .catch(error => {
173
- this.working = false;
174
- void showErrorMessage('Jupyterlab Code Formatter Error', error);
175
- });
213
+ else if (defaultFormatter !== undefined) {
214
+ return [defaultFormatter];
215
+ }
216
+ }
217
+ return [];
218
+ }
219
+ async getFormattersToUse(config, formatter) {
220
+ const defaultFormatters = this.getDefaultFormatters(config);
221
+ const formattersToUse = formatter !== undefined ? [formatter] : defaultFormatters;
222
+ if (formattersToUse.length === 0) {
223
+ await showErrorMessage('Jupyterlab Code Formatter Error', 'Unable to find default formatters to use, please file an issue on GitHub.');
224
+ }
225
+ return formattersToUse;
226
+ }
227
+ async applyFormatters(formattersToUse, config, context) {
228
+ var _a, _b;
229
+ for (const formatterToUse of formattersToUse) {
230
+ if (formatterToUse === 'noop' || formatterToUse === 'skip') {
231
+ continue;
232
+ }
233
+ const showErrors = !((_a = config.suppressFormatterErrors) !== null && _a !== void 0 ? _a : false) &&
234
+ !(((_b = config.suppressFormatterErrorsIFFAutoFormatOnSave) !== null && _b !== void 0 ? _b : false) &&
235
+ context.saving);
236
+ const editorWidget = this.editorTracker.currentWidget;
237
+ this.working = true;
238
+ const editor = editorWidget.content.editor;
239
+ const code = editor.model.sharedModel.source;
240
+ this.formatCode([code], formatterToUse, config[formatterToUse], false, config.cacheFormatters)
241
+ .then(data => {
242
+ if (data.code[0].error) {
243
+ if (showErrors) {
244
+ void showErrorMessage('Jupyterlab Code Formatter Error', data.code[0].error);
245
+ }
246
+ this.working = false;
247
+ return;
248
+ }
249
+ this.editorTracker.currentWidget.content.editor.model.sharedModel.source =
250
+ data.code[0].code;
251
+ this.working = false;
252
+ })
253
+ .catch(error => {
254
+ const msg = error instanceof Error ? error : `${error}`;
255
+ void showErrorMessage('Jupyterlab Code Formatter Error', msg);
256
+ });
257
+ }
176
258
  }
177
259
  applicable(formatter, currentWidget) {
178
260
  const currentEditorWidget = this.editorTracker.currentWidget;
package/lib/index.js CHANGED
@@ -33,7 +33,7 @@ class JupyterLabCodeFormatter {
33
33
  svgstr: Constants.ICON_FORMAT_ALL_SVG
34
34
  }),
35
35
  onClick: async () => {
36
- await this.notebookCodeFormatter.formatAllCodeCells(this.config, undefined, nb.content);
36
+ await this.notebookCodeFormatter.formatAllCodeCells(this.config, { saving: false }, undefined, nb.content);
37
37
  }
38
38
  });
39
39
  nb.toolbar.insertAfter('cellType', this.app.commands.label(Constants.FORMAT_ALL_COMMAND), button);
@@ -44,11 +44,27 @@ class JupyterLabCodeFormatter {
44
44
  }
45
45
  async onSave(context, state) {
46
46
  if (state === 'started' && this.config.formatOnSave) {
47
- await this.notebookCodeFormatter.formatAllCodeCells(this.config);
47
+ await this.notebookCodeFormatter.formatAllCodeCells(this.config, { saving: true }, undefined, undefined);
48
+ }
49
+ }
50
+ createNewEditor(widget, context) {
51
+ // Connect to save(State) signal, to be able to detect document save event
52
+ context.saveState.connect(this.onSaveEditor, this);
53
+ // Return an empty disposable, because we don't create any object
54
+ return new DisposableDelegate(() => { });
55
+ }
56
+ async onSaveEditor(context, state) {
57
+ if (state === 'started' && this.config.formatOnSave) {
58
+ this.fileEditorCodeFormatter.formatEditor(this.config, { saving: true }, undefined);
48
59
  }
49
60
  }
50
61
  setupWidgetExtension() {
51
62
  this.app.docRegistry.addWidgetExtension('Notebook', this);
63
+ this.app.docRegistry.addWidgetExtension('editor', {
64
+ createNew: (widget, context) => {
65
+ return this.createNewEditor(widget, context);
66
+ }
67
+ });
52
68
  }
53
69
  setupContextMenu() {
54
70
  this.app.contextMenu.addItem({
@@ -80,7 +96,9 @@ class JupyterLabCodeFormatter {
80
96
  });
81
97
  this.app.commands.addCommand(Constants.FORMAT_ALL_COMMAND, {
82
98
  execute: async () => {
83
- await this.notebookCodeFormatter.formatAllCodeCells(this.config);
99
+ await this.notebookCodeFormatter.formatAllCodeCells(this.config, {
100
+ saving: false
101
+ });
84
102
  },
85
103
  iconClass: Constants.ICON_FORMAT_ALL,
86
104
  iconLabel: 'Format notebook'
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "jupyterlab_code_formatter",
3
- "version": "2.2.1",
3
+ "version": "3.0.1",
4
4
  "description": " A JupyterLab plugin to facilitate invocation of code formatters.",
5
5
  "keywords": [
6
6
  "jupyter",
7
7
  "jupyterlab",
8
8
  "jupyterlab-extension"
9
9
  ],
10
- "homepage": " https://github.com/ryantam626/jupyterlab_code_formatter",
10
+ "homepage": " https://github.com/jupyterlab-contrib/jupyterlab_code_formatter",
11
11
  "bugs": {
12
- "url": " https://github.com/ryantam626/jupyterlab_code_formatter/issues"
12
+ "url": " https://github.com/jupyterlab-contrib/jupyterlab_code_formatter/issues"
13
13
  },
14
14
  "license": "BSD-3-Clause",
15
15
  "author": {
@@ -26,7 +26,7 @@
26
26
  "style": "style/index.css",
27
27
  "repository": {
28
28
  "type": "git",
29
- "url": " https://github.com/ryantam626/jupyterlab_code_formatter.git"
29
+ "url": " https://github.com/jupyterlab-contrib/jupyterlab_code_formatter.git"
30
30
  },
31
31
  "scripts": {
32
32
  "build": "jlpm build:lib && jlpm build:labextension:dev",
@@ -56,36 +56,40 @@
56
56
  "watch:labextension": "jupyter labextension watch ."
57
57
  },
58
58
  "dependencies": {
59
- "@jupyterlab/application": "^3.6.0 || ~4.0.0",
60
- "@jupyterlab/coreutils": "^5.1.0",
61
- "@jupyterlab/fileeditor": "^3.6.0 || ~4.0.0",
62
- "@jupyterlab/mainmenu": "^3.6.0 || ~4.0.0",
63
- "@jupyterlab/services": "^6.1.0",
64
- "@jupyterlab/settingregistry": "^3.6.0 || ~4.0.0"
59
+ "@jupyterlab/application": "^4.0.0",
60
+ "@jupyterlab/coreutils": "^6.0.0",
61
+ "@jupyterlab/fileeditor": "^4.0.0",
62
+ "@jupyterlab/mainmenu": "^4.0.0",
63
+ "@jupyterlab/services": "^7.0.0",
64
+ "@jupyterlab/settingregistry": "^4.0.0"
65
65
  },
66
66
  "devDependencies": {
67
- "@babel/core": "^7.0.0",
68
- "@babel/preset-env": "^7.0.0",
69
- "@jupyterlab/builder": "^3.6.0 || ~4.0.0",
70
- "@jupyterlab/testutils": "^3.6.0 || ~4.0.0",
71
- "@types/jest": "^26.0.0",
72
- "@typescript-eslint/eslint-plugin": "^4.8.1",
73
- "@typescript-eslint/parser": "^4.8.1",
74
- "eslint": "^7.14.0",
75
- "eslint-config-prettier": "^6.15.0",
76
- "eslint-plugin-prettier": "^3.1.4",
77
- "jest": "^26.0.0",
67
+ "@jupyterlab/builder": "^4.2.3",
68
+ "@jupyterlab/testutils": "^4.0.0",
69
+ "@types/jest": "^29.2.0",
70
+ "@types/json-schema": "^7.0.11",
71
+ "@types/react": "^18.0.26",
72
+ "@types/react-addons-linked-state-mixin": "^0.14.22",
73
+ "@typescript-eslint/eslint-plugin": "^6.1.0",
74
+ "@typescript-eslint/parser": "^6.1.0",
75
+ "css-loader": "^6.7.1",
76
+ "eslint": "^8.36.0",
77
+ "eslint-config-prettier": "^8.8.0",
78
+ "eslint-plugin-prettier": "^5.0.0",
79
+ "jest": "^29.2.0",
78
80
  "mkdirp": "^1.0.3",
79
81
  "npm-run-all": "^4.1.5",
80
- "prettier": "^2.1.1",
81
- "rimraf": "^3.0.2",
82
- "stylelint": "^14.3.0",
83
- "stylelint-config-prettier": "^9.0.4",
84
- "stylelint-config-recommended": "^6.0.0",
85
- "stylelint-config-standard": "~24.0.0",
86
- "stylelint-prettier": "^2.0.0",
87
- "ts-jest": "^26.0.0",
88
- "typescript": "~4.1.3"
82
+ "prettier": "^3.0.0",
83
+ "rimraf": "^5.0.1",
84
+ "source-map-loader": "^1.0.2",
85
+ "style-loader": "^3.3.1",
86
+ "stylelint": "^15.10.1",
87
+ "stylelint-config-recommended": "^13.0.0",
88
+ "stylelint-config-standard": "^34.0.0",
89
+ "stylelint-csstree-validator": "^3.0.0",
90
+ "stylelint-prettier": "^4.0.0",
91
+ "typescript": "~5.0.2",
92
+ "yjs": "^13.5.0"
89
93
  },
90
94
  "sideEffects": [
91
95
  "style/*.css",
@@ -177,7 +181,15 @@
177
181
  "singleQuote": true,
178
182
  "trailingComma": "none",
179
183
  "arrowParens": "avoid",
180
- "endOfLine": "auto"
184
+ "endOfLine": "auto",
185
+ "overrides": [
186
+ {
187
+ "files": "package.json",
188
+ "options": {
189
+ "tabWidth": 4
190
+ }
191
+ }
192
+ ]
181
193
  },
182
194
  "stylelint": {
183
195
  "extends": [
@@ -185,7 +197,11 @@
185
197
  "stylelint-config-standard",
186
198
  "stylelint-prettier/recommended"
187
199
  ],
200
+ "plugins": [
201
+ "stylelint-csstree-validator"
202
+ ],
188
203
  "rules": {
204
+ "csstree/validator": true,
189
205
  "property-no-vendor-prefix": null,
190
206
  "selector-no-vendor-prefix": null,
191
207
  "value-no-vendor-prefix": null
@@ -208,6 +208,13 @@
208
208
  "additionalProperties": false,
209
209
  "type": "object"
210
210
  },
211
+ "ruffformat": {
212
+ "properties": {
213
+ "args": { "type": "array", "items": { "type": "string" } }
214
+ },
215
+ "additionalProperties": false,
216
+ "type": "object"
217
+ },
211
218
  "formatR": {
212
219
  "properties": {
213
220
  "comment": {
@@ -313,6 +320,10 @@
313
320
  "suppressFormatterErrors": {
314
321
  "additionalProperties": false,
315
322
  "type": "boolean"
323
+ },
324
+ "suppressFormatterErrorsIFFAutoFormatOnSave": {
325
+ "additionalProperties": false,
326
+ "type": "boolean"
316
327
  }
317
328
  },
318
329
  "properties": {
@@ -403,11 +414,19 @@
403
414
  }
404
415
  },
405
416
  "ruff": {
406
- "title": "Ruff Config",
407
- "description": "Command line options to be passed to ruff.",
417
+ "title": "Ruff Check Config",
418
+ "description": "Command line options to be passed to ruff check. Default is to organise imports.",
408
419
  "$ref": "#/definitions/ruff",
409
420
  "default": {
410
- "args": ["--select=I"]
421
+ "args": ["--select=I001"]
422
+ }
423
+ },
424
+ "ruffformat": {
425
+ "title": "Ruff Format Config",
426
+ "description": "Command line options to be passed to ruff format.",
427
+ "$ref": "#/definitions/ruffformat",
428
+ "default": {
429
+ "args": []
411
430
  }
412
431
  },
413
432
  "suppressFormatterErrors": {
@@ -415,6 +434,12 @@
415
434
  "description": "Whether to suppress all errors reported by formatter while formatting. Useful when you have format on save mode on.",
416
435
  "$ref": "#/definitions/suppressFormatterErrors",
417
436
  "default": false
437
+ },
438
+ "suppressFormatterErrorsIFFAutoFormatOnSave": {
439
+ "title": "Suppress formatter errors if and only if auto saving.",
440
+ "description": "Whether to suppress all errors reported by formatter while formatting (if and only if auto saving). Useful when you have format on save mode on and still want to see error when manually formatting.",
441
+ "$ref": "#/definitions/suppressFormatterErrorsIFFAutoFormatOnSave",
442
+ "default": false
418
443
  }
419
444
  },
420
445
  "additionalProperties": false,