@starci/eslint-canon-fe 9.16.2 → 9.16.3
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 9.16.3 - 2026-11-07
|
|
4
|
+
|
|
5
|
+
- Added (R235 `SCAN_SMELL`, `no-line-separator-literal`, slot-free): a raw U+2028, U+2029 or U+0085 anywhere in a file, specs included, is an error that names the escape to write (`
`, `
`, `
`) in a string, template or regular expression, or says to delete the character elsewhere. The Sonar scanner splits lines at these characters and TypeScript does not, so its analysis aborts with "Line n is out of range ... File has m lines".
|
|
6
|
+
|
|
3
7
|
## 9.16.2 - 2026-11-07
|
|
4
8
|
|
|
5
9
|
- A patch: peers `@starci/hfs` ~6.0.0. Comments, rule docs and messages cite rules by their ids and carry no ruling history; the counting cohort entries carry no ruling field.
|
package/dist/lib/config.js
CHANGED
|
@@ -103,7 +103,7 @@ export const SLOT_FREE_RULES = Object.freeze([
|
|
|
103
103
|
"handler-on-prefix", "no-native-form-control", "no-native-img", "image-has-size", "no-second-i18n-stack", "html-lang-from-locale", "no-null-suspense-fallback",
|
|
104
104
|
"no-native-anchor", "no-inline-parameter-type", "no-hand-rolled-polling", "no-copy-in-call", "no-alert", "no-failure-collapse",
|
|
105
105
|
"outcome-kinds-exhaustive", "no-await-in-loop", "prefer-code-point", "prefer-string-raw", "no-nested-conditional", "no-void-operator", "no-unused-import",
|
|
106
|
-
"prefer-export-from", "no-unused-prop-types", "media-has-caption", "max-params",
|
|
106
|
+
"prefer-export-from", "no-unused-prop-types", "media-has-caption", "max-params", "no-line-separator-literal",
|
|
107
107
|
"no-list-panel-padding", "no-hand-built-panes", "no-table-in-card", "no-heading-above-card", "no-selectable-tag-group", "no-fill-command-in-header", "no-app-surface-paint", "divider-full-bleed", "control-height", "selection-fill-no-check", "no-grammar-shim",
|
|
108
108
|
"no-swr-default-array", "no-foreign-slot-status", "no-validating-as-loading", "no-placeholder-object", "no-hand-skeleton", "explicit-export-surface", "directive-first", "renderer-presentation-only",
|
|
109
109
|
"button-intent-required", "destructive-confirm-in-dialog", "single-commit-per-render", "no-commit-in-collection-item",
|
package/dist/sonar-parity.js
CHANGED
|
@@ -17,7 +17,7 @@ const syntaxRule = (name) => {
|
|
|
17
17
|
throw new TypeError(`the runtime Sonar syntax rules publish no ${name}`);
|
|
18
18
|
return rule;
|
|
19
19
|
};
|
|
20
|
-
const NAMES = ["no-await-in-loop", "prefer-code-point", "prefer-string-raw", "no-nested-conditional", "no-void-operator", "no-unused-import", "prefer-export-from", "no-unused-prop-types", "media-has-caption", "max-params"];
|
|
20
|
+
const NAMES = ["no-await-in-loop", "prefer-code-point", "prefer-string-raw", "no-nested-conditional", "no-void-operator", "no-unused-import", "prefer-export-from", "no-unused-prop-types", "media-has-caption", "max-params", "no-line-separator-literal"];
|
|
21
21
|
/** The rules this law contributes to the plugin. */
|
|
22
22
|
export const rules = Object.fromEntries(NAMES.map((name) => [name, syntaxRule(name)]));
|
|
23
23
|
/** Starts at error: a repository's fix lane clears the debt before the rule ships. */
|
package/package.json
CHANGED
|
@@ -247,6 +247,23 @@ const mediaHasCaption = {
|
|
|
247
247
|
},
|
|
248
248
|
};
|
|
249
249
|
|
|
250
|
+
/** The line breaks the scanner counts and the language does not: a raw U+2028 or U+2029 inside a string, template, regular expression or comment is legal source, and U+0085 is no line terminator in it. */
|
|
251
|
+
const SCANNER_LINE_BREAKS = /[\u2028\u2029\u0085]/gu;
|
|
252
|
+
const LINE_BREAK_NAMES = Object.freeze({ '\u2028': ['U+2028', 'LINE SEPARATOR', '\\u2028'], '\u2029': ['U+2029', 'PARAGRAPH SEPARATOR', '\\u2029'], '\u0085': ['U+0085', 'NEXT LINE', '\\u0085'] });
|
|
253
|
+
/** Sonar scanner crash ("Line n is out of range ... File has m lines"): the scanner splits a file at U+2028, U+2029 and U+0085, the language service does not, so their line numbers disagree and the analysis aborts. Applies to every file the scan reads, specs included. */
|
|
254
|
+
const noLineSeparatorLiteral = {
|
|
255
|
+
meta: { type: 'problem', schema: [], messages: { raw: 'The scanner splits lines at a raw {{ code }} ({{ name }}) and TypeScript does not, so its analysis aborts with "Line n is out of range". Write the escape `{{ escape }}` in a string, template or regular expression, or delete the character anywhere else.' } },
|
|
256
|
+
create: (context) => ({
|
|
257
|
+
Program: () => {
|
|
258
|
+
const { text } = context.sourceCode;
|
|
259
|
+
for (const found of text.matchAll(SCANNER_LINE_BREAKS)) {
|
|
260
|
+
const [code, name, escape] = LINE_BREAK_NAMES[found[0]];
|
|
261
|
+
context.report({ loc: context.sourceCode.getLocFromIndex(found.index), messageId: 'raw', data: { code, name, escape } });
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
}),
|
|
265
|
+
};
|
|
266
|
+
|
|
250
267
|
/** The files the example scans leave out: a unit spec and an end-to-end spec (the regex, and the flat-config globs of the same set). */
|
|
251
268
|
const OUTSIDE_THE_SCAN = /\.(?:e2e-)?spec\.[cm]?[jt]sx?$/;
|
|
252
269
|
export const OUTSIDE_THE_SCAN_FILES = Object.freeze(['**/*.spec.{js,mjs,cjs,ts,mts,cts,jsx,tsx}', '**/*.e2e-spec.{js,mjs,cjs,ts,mts,cts,jsx,tsx}']);
|
|
@@ -266,4 +283,5 @@ export const SONAR_SYNTAX_RULES = Object.freeze({
|
|
|
266
283
|
'no-unused-prop-types': scanned(noUnusedPropTypes),
|
|
267
284
|
'media-has-caption': scanned(mediaHasCaption),
|
|
268
285
|
'max-params': scanned(maxParams),
|
|
286
|
+
'no-line-separator-literal': noLineSeparatorLiteral,
|
|
269
287
|
});
|