@lvce-editor/eslint-plugin-extension-json 17.3.1 → 17.5.0

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.
Files changed (2) hide show
  1. package/dist/index.js +120 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ const findMember = (node, name) => {
31
31
  };
32
32
 
33
33
  const requiredFirstDirective = "default-src 'none'";
34
- const meta = {
34
+ const meta$1 = {
35
35
  docs: {
36
36
  description: 'Require a secure content security policy for extension workers'
37
37
  },
@@ -48,7 +48,7 @@ const hasMainEntry = manifest => {
48
48
  const isValidPolicyArray = node => {
49
49
  return isArrayNode(node) && node.elements.every(element => isStringNode(element.value));
50
50
  };
51
- const create = context => {
51
+ const create$1 = context => {
52
52
  return {
53
53
  Document(node) {
54
54
  if (!isObjectNode(node.body)) {
@@ -83,6 +83,120 @@ const create = context => {
83
83
  };
84
84
 
85
85
  const contentSecurityPolicy = {
86
+ __proto__: null,
87
+ create: create$1,
88
+ meta: meta$1
89
+ };
90
+
91
+ // cspell:ignore ctrlcmd downarrow leftarrow rightarrow uparrow
92
+ const identifierPattern = /^\w[\w-]*(?:\.\w[\w-]*)+$/;
93
+ const keyNames = new Set(['`', ',', '-', '=', '*', '\\', 'backquote', 'backslash', 'comma', 'delete', 'down', 'downarrow', 'end', 'enter', 'escape', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', 'f11', 'f12', 'home', 'insert', 'left', 'leftarrow', 'minus', 'pagedown', 'pageup', 'plus', 'right', 'rightarrow', 'space', 'tab', 'up', 'uparrow']);
94
+ const modifierGroups = new Map([['alt', 'alt'], ['cmd', 'ctrlCmd'], ['command', 'ctrlCmd'], ['ctrl', 'ctrlCmd'], ['ctrlcmd', 'ctrlCmd'], ['meta', 'ctrlCmd'], ['shift', 'shift']]);
95
+ const meta = {
96
+ docs: {
97
+ description: 'Require valid keybinding contributions in extension manifests'
98
+ },
99
+ messages: {
100
+ invalidCommand: 'extension keybinding command must be a dot-separated ASCII identifier',
101
+ invalidKey: 'extension keybinding key is invalid',
102
+ invalidKeybinding: 'extension keybinding must be an object with string key and command properties',
103
+ invalidKeybindings: 'extension keybindings must be an array',
104
+ invalidWhenExpression: 'extension keybinding when expression must be a dot-separated ASCII identifier'
105
+ },
106
+ type: 'problem'
107
+ };
108
+ const isIdentifier = value => {
109
+ return identifierPattern.test(value);
110
+ };
111
+ const isKeyName = value => {
112
+ return /^[a-z0-9]$/i.test(value) || keyNames.has(value.toLowerCase());
113
+ };
114
+ const isValidKey = value => {
115
+ const parts = value.split('+').map(part => part.trim());
116
+ if (parts.length === 0 || parts.some(part => !part)) {
117
+ return false;
118
+ }
119
+ const seenModifiers = new Set();
120
+ let keyCount = 0;
121
+ for (const part of parts) {
122
+ const normalized = part.toLowerCase();
123
+ const modifierGroup = modifierGroups.get(normalized);
124
+ if (modifierGroup) {
125
+ if (seenModifiers.has(modifierGroup)) {
126
+ return false;
127
+ }
128
+ seenModifiers.add(modifierGroup);
129
+ continue;
130
+ }
131
+ if (!isKeyName(part)) {
132
+ return false;
133
+ }
134
+ keyCount++;
135
+ }
136
+ return keyCount === 1;
137
+ };
138
+ const reportKeybinding = (context, keybinding) => {
139
+ if (!isObjectNode(keybinding)) {
140
+ context.report({
141
+ loc: keybinding.loc,
142
+ messageId: 'invalidKeybinding'
143
+ });
144
+ return;
145
+ }
146
+ const key = findMember(keybinding, 'key');
147
+ const command = findMember(keybinding, 'command');
148
+ if (!key || !command || !isStringNode(key.value) || !isStringNode(command.value)) {
149
+ context.report({
150
+ loc: keybinding.loc,
151
+ messageId: 'invalidKeybinding'
152
+ });
153
+ return;
154
+ }
155
+ if (!isValidKey(key.value.value)) {
156
+ context.report({
157
+ loc: key.name.loc,
158
+ messageId: 'invalidKey'
159
+ });
160
+ }
161
+ if (!isIdentifier(command.value.value)) {
162
+ context.report({
163
+ loc: command.name.loc,
164
+ messageId: 'invalidCommand'
165
+ });
166
+ }
167
+ const when = findMember(keybinding, 'when');
168
+ if (when && (!isStringNode(when.value) || !isIdentifier(when.value.value))) {
169
+ context.report({
170
+ loc: when.name.loc,
171
+ messageId: 'invalidWhenExpression'
172
+ });
173
+ }
174
+ };
175
+ const create = context => {
176
+ return {
177
+ Document(node) {
178
+ if (!isObjectNode(node.body)) {
179
+ return;
180
+ }
181
+ const keybindings = findMember(node.body, 'keybindings');
182
+ if (!keybindings) {
183
+ return;
184
+ }
185
+ if (!isArrayNode(keybindings.value)) {
186
+ context.report({
187
+ loc: keybindings.name.loc,
188
+ messageId: 'invalidKeybindings'
189
+ });
190
+ return;
191
+ }
192
+ for (const element of keybindings.value.elements) {
193
+ reportKeybinding(context, element.value);
194
+ }
195
+ }
196
+ };
197
+ };
198
+
199
+ const validKeybindings = {
86
200
  __proto__: null,
87
201
  create,
88
202
  meta
@@ -95,7 +209,8 @@ const plugin = {
95
209
  version: '0.0.1'
96
210
  },
97
211
  rules: {
98
- 'content-security-policy': contentSecurityPolicy
212
+ 'content-security-policy': contentSecurityPolicy,
213
+ 'valid-keybindings': validKeybindings
99
214
  }
100
215
  };
101
216
  const recommended = [{
@@ -107,7 +222,8 @@ const recommended = [{
107
222
  json
108
223
  },
109
224
  rules: {
110
- 'extension-json/content-security-policy': 'error'
225
+ 'extension-json/content-security-policy': 'error',
226
+ 'extension-json/valid-keybindings': 'error'
111
227
  }
112
228
  }];
113
229
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/eslint-plugin-extension-json",
3
- "version": "17.3.1",
3
+ "version": "17.5.0",
4
4
  "main": "dist/index.js",
5
5
  "repository": {
6
6
  "type": "git",