From 98470b15c4f5b580a11c49e3e8590d85eb6ef785 Mon Sep 17 00:00:00 2001 From: Splines <37160523+Splines@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:31:06 +0100 Subject: [PATCH 1/4] Add Mocha JS tests & fix ERB Regex (#2) * Init Mocha tests for preprocessor & fix ERB Regex * Omit fixtures from mocha * Add tests for offset map construction in preprocessing * Fix wording in comment * Add test for multiple ERB tags in one line * Add tests for postprocessing * Run tests in CI/CD pipeline * Reduce test matrix (get rid of eslint versions) * Run tests on dev branch * Add Readme describing tests --- .github/workflows/test.yml | 29 ++ .mocharc.js | 6 + lib/erb_regex.js | 14 - lib/offset_map.js | 15 +- lib/preprocess.js | 6 +- package.json | 7 +- tests/.eslintrc.yml | 2 + tests/README.md | 72 +++ tests/fixtures/common.expected.messages.js | 410 ++++++++++++++++++ tests/fixtures/common.js | 13 + tests/fixtures/common.messages.js | 405 +++++++++++++++++ tests/fixtures/common.pre.js | 12 + tests/fixtures/each-do.expected.messages.js | 69 +++ tests/fixtures/each-do.js | 3 + tests/fixtures/each-do.messages.js | 69 +++ tests/fixtures/each-do.pre.js | 3 + .../fixtures/multi-line.expected.messages.js | 81 ++++ tests/fixtures/multi-line.js | 5 + tests/fixtures/multi-line.messages.js | 81 ++++ tests/fixtures/multi-line.pre.js | 3 + ...tiple-erb-in-one-line.expected.messages.js | 215 +++++++++ tests/fixtures/multiple-erb-in-one-line.js | 1 + .../multiple-erb-in-one-line.messages.js | 215 +++++++++ .../fixtures/multiple-erb-in-one-line.pre.js | 1 + tests/fixtures/one-liner.expected.messages.js | 29 ++ tests/fixtures/one-liner.js | 1 + tests/fixtures/one-liner.messages.js | 29 ++ tests/fixtures/one-liner.pre.js | 1 + tests/postprocess.js | 41 ++ tests/preprocess.js | 146 +++++++ yarn.lock | 369 +++++++++++++++- 31 files changed, 2320 insertions(+), 33 deletions(-) create mode 100644 .github/workflows/test.yml create mode 100644 .mocharc.js delete mode 100644 lib/erb_regex.js create mode 100644 tests/.eslintrc.yml create mode 100644 tests/README.md create mode 100644 tests/fixtures/common.expected.messages.js create mode 100644 tests/fixtures/common.js create mode 100644 tests/fixtures/common.messages.js create mode 100644 tests/fixtures/common.pre.js create mode 100644 tests/fixtures/each-do.expected.messages.js create mode 100644 tests/fixtures/each-do.js create mode 100644 tests/fixtures/each-do.messages.js create mode 100644 tests/fixtures/each-do.pre.js create mode 100644 tests/fixtures/multi-line.expected.messages.js create mode 100644 tests/fixtures/multi-line.js create mode 100644 tests/fixtures/multi-line.messages.js create mode 100644 tests/fixtures/multi-line.pre.js create mode 100644 tests/fixtures/multiple-erb-in-one-line.expected.messages.js create mode 100644 tests/fixtures/multiple-erb-in-one-line.js create mode 100644 tests/fixtures/multiple-erb-in-one-line.messages.js create mode 100644 tests/fixtures/multiple-erb-in-one-line.pre.js create mode 100644 tests/fixtures/one-liner.expected.messages.js create mode 100644 tests/fixtures/one-liner.js create mode 100644 tests/fixtures/one-liner.messages.js create mode 100644 tests/fixtures/one-liner.pre.js create mode 100644 tests/postprocess.js create mode 100644 tests/preprocess.js diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..39276d4 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,29 @@ +name: Tests + +on: + push: + branches: [main, dev] + pull_request: + types: [opened, reopened, synchronize, ready_for_review] + +jobs: + mocha: + name: Mocha + strategy: + matrix: + os: [ubuntu-latest] + node: [16, 17, 18, 19, 20, 21] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Node.js ${{ matrix.node }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + - name: Install dependencies + run: npm install + env: + CI: true + - name: Run Mocha tests + run: npm test diff --git a/.mocharc.js b/.mocharc.js new file mode 100644 index 0000000..c006647 --- /dev/null +++ b/.mocharc.js @@ -0,0 +1,6 @@ +module.exports = { + "spec": "tests/**/*.js", + "ignore": [ + "tests/fixtures/**" + ], +} \ No newline at end of file diff --git a/lib/erb_regex.js b/lib/erb_regex.js deleted file mode 100644 index 7d4bb06..0000000 --- a/lib/erb_regex.js +++ /dev/null @@ -1,14 +0,0 @@ -const erbRegex = /<%[\s\S]*?%>/g; - -const erbRegexSingleQuoted = new RegExp("'" + erbRegex.source + "'", "g"); -const erbRegexDoubleQuoted = new RegExp("\"" + erbRegex.source + "\"", "g"); -const erbRegexBacktickQuoted = new RegExp("`" + erbRegex.source + "`", "g"); - -const erbRegexChained = new RegExp( - erbRegex.source + "|" + erbRegexSingleQuoted.source - + "|" + erbRegexDoubleQuoted.source + "|" + erbRegexBacktickQuoted.source, "g", -); - -module.exports = { - erbRegexChained, -}; diff --git a/lib/offset_map.js b/lib/offset_map.js index 814e334..6edd06e 100644 --- a/lib/offset_map.js +++ b/lib/offset_map.js @@ -10,6 +10,9 @@ this.lineOffsetLookup = { 21 => Map(1) { 942 => [ 6, 95 ] } } +For brevity, we emit the respective property names and show the values in an +array instead. First number is line offset, second number is column offset. + this.offsetLookup = { 43 => [ 0, -23 ], 92 => [ 0, -17 ], @@ -21,8 +24,16 @@ this.offsetLookup = { 942 => [ 6, 95 ] } -Each index stored corresponds to an "end index" of the respective ERB tag, -but when it it processed already, i. e. replaced by a dummy comment. +We store the end index of the respective ERB tag and use that as key for our map. +Note that this end index refers to the processed text, i. e. the text after +replacing ERB tags with dummy comments. +The index is an index to the whole text. +Note that line offsets accumulate. + +And to add to the good old off-by-one confusion: +Line offsets: 1-based +Column offsets: 0-based +(also see file coordinates) */ diff --git a/lib/preprocess.js b/lib/preprocess.js index 3bc08d6..cbb99d0 100644 --- a/lib/preprocess.js +++ b/lib/preprocess.js @@ -4,11 +4,11 @@ const cache = require("./cache.js"); const { indexToColumn } = require("./file_coordinates.js"); -const regex = require("./erb_regex.js"); -// how annoying is that kind of important in JS ?! +// how annoying is that kind of import in JS ?! var OffsetMap = require("./offset_map.js").OffsetMap; +const erbRegex = /<%[\s\S]*?%>/g; const DUMMY_STR = "/* eslint-disable */{}/* eslint-enable */"; const DUMMY_LEN = DUMMY_STR.length; @@ -29,7 +29,7 @@ function preprocess(text, filename) { let numDiffChars = 0; const offsetMap = new OffsetMap(); - while ((match = regex.erbRegexChained.exec(text)) !== null) { + while ((match = erbRegex.exec(text)) !== null) { // Match information const startIndex = match.index; const matchText = match[0]; diff --git a/package.json b/package.json index f9dc9b7..410c210 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,11 @@ "main": "index.js", "devDependencies": { "@stylistic/eslint-plugin": "^1.3.3", - "eslint": "^8.54.0" + "chai": "^4.3.10", + "eslint": "^8.54.0", + "mocha": "^10.2.0" + }, + "scripts": { + "test": "mocha" } } diff --git a/tests/.eslintrc.yml b/tests/.eslintrc.yml new file mode 100644 index 0000000..7e104db --- /dev/null +++ b/tests/.eslintrc.yml @@ -0,0 +1,2 @@ +env: + mocha: true \ No newline at end of file diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..12ca7e9 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,72 @@ +# Testing + + +## Run tests + +```sh +npm test +``` + + +## Environment + +For reproduction, this is the ESLint configuration file used to generate the input messages for testing (see the `tests/fixtures/` folder. The files were manually renamed to end with `.js.erb` during this process. + +```js +//.eslintrc.js +// Starting with v9, this config will be deprecated in favor of the new +// configuration files [1]. @stylistic is already ready for the new "flat config", +// when it's time, copy the new config from [2]. +// [1] https://eslint.org/docs/latest/use/configure/configuration-files-new +// [2] https://eslint.style/guide/config-presets#configuration-factory + +// ////////////////////////////////////////// +// Stylistic Plugin for ESLint +// ////////////////////////////////////////// +// see the rules in [3] and [4]. +// [3] https://eslint.style/packages/js#rules +// [4] https://eslint.org/docs/rules/ + +// eslint-disable-next-line no-undef +require("@stylistic/eslint-plugin"); + +// eslint-disable-next-line no-undef +module.exports = { + "root": true, + "parserOptions": { + "ecmaVersion": 2024, + "sourceType": "module" + }, + "env": { + "browser": true, + "jquery": true, + "es6": true + }, + "extends": [ + "eslint:recommended", + "plugin:@stylistic/all-extends" + ], + "plugins": [ + "@stylistic", + "erb" + ], + "overrides": [ + { + "files": ["*.js.erb"], + "processor": "erb/erbProcessor" + } + ], + "rules": { + "no-unused-vars": "warn", + "@stylistic/indent": ["error", 2], + "@stylistic/quotes": ["error", "double"], + "@stylistic/array-element-newline": ["error", "consistent"], + "@stylistic/max-len": [ + "error", { + "code": 100, + "ignoreUrls": true + } + ] + } +}; +``` \ No newline at end of file diff --git a/tests/fixtures/common.expected.messages.js b/tests/fixtures/common.expected.messages.js new file mode 100644 index 0000000..0488547 --- /dev/null +++ b/tests/fixtures/common.expected.messages.js @@ -0,0 +1,410 @@ +// To be honest: this file was auto-generated and not manually checked. +// Should be fine though as the outcome is exactly what is expected. +// (by checking in the IDE that all the autofixes work as assumed) + +const messages = [ + { + ruleId: "@stylistic/no-multi-spaces", + severity: 2, + message: "Multiple spaces found before '('.", + line: 1, + column: 3, + nodeType: "Punctuator", + messageId: "multipleSpaces", + endLine: 1, + endColumn: 9, + fix: { range: [2, 8], text: " " }, + }, + { + ruleId: "no-constant-condition", + severity: 2, + message: "Unexpected constant condition.", + line: 1, + column: 30, + nodeType: "ObjectExpression", + messageId: "unexpected", + endLine: 1, + endColumn: 32, + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/no-multi-spaces", + severity: 2, + message: "Multiple spaces found before ')'.", + line: 1, + column: 25, + nodeType: "Punctuator", + messageId: "multipleSpaces", + endLine: 1, + endColumn: 30, + fix: { range: [24, 29], text: " " }, + }, + { + ruleId: "@stylistic/space-in-parens", + severity: 2, + message: "There should be no space before this paren.", + line: 1, + column: 25, + nodeType: "Program", + messageId: "rejectedClosingSpace", + endLine: 1, + endColumn: 30, + fix: { range: [24, 29], text: "" }, + }, + { + ruleId: "@stylistic/padded-blocks", + severity: 2, + message: "Block must be padded by blank lines.", + line: 1, + column: 32, + nodeType: "BlockStatement", + messageId: "alwaysPadBlock", + endLine: 2, + endColumn: 5, + fix: { range: [32, 32], text: "\n" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 2 spaces but found 4.", + line: 2, + column: 1, + nodeType: "Identifier", + messageId: "wrongIndentation", + endLine: 2, + endColumn: 5, + fix: { range: [33, 37], text: " " }, + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 2, + column: 17, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 2, + endColumn: 29, + fix: { range: [49, 61], text: "\"Success 🎉\"" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 2 spaces but found 5.", + line: 3, + column: 1, + nodeType: "Identifier", + messageId: "wrongIndentation", + endLine: 3, + endColumn: 6, + fix: { range: [64, 69], text: " " }, + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 3, + column: 8, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 3, + endColumn: 15, + fix: { range: [71, 78], text: "\"#yeah\"" }, + }, + { + ruleId: "@stylistic/no-multi-spaces", + severity: 2, + message: "Multiple spaces found before ''/* eslint-disable */{}/* eslint-enable */''.", + line: 3, + column: 22, + nodeType: "String", + messageId: "multipleSpaces", + endLine: 3, + endColumn: 24, + fix: { range: [85, 87], text: " " }, + }, + { + ruleId: "@stylistic/space-in-parens", + severity: 2, + message: "There should be no space after this paren.", + line: 3, + column: 22, + nodeType: "Program", + messageId: "rejectedOpeningSpace", + endLine: 3, + endColumn: 24, + fix: { range: [85, 87], text: "" }, + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 3, + column: 24, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 4, + endColumn: 54, + fix: { + range: [87, 171], + text: `"<%= j render partial: 'yeah',\n` + + " locals: { cool: @cool } %>\"", + }, + }, + { + ruleId: "@stylistic/no-multi-spaces", + severity: 2, + message: "Multiple spaces found before ')'.", + line: 4, + column: 54, + nodeType: "Punctuator", + messageId: "multipleSpaces", + endLine: 4, + endColumn: 59, + fix: { range: [171, 176], text: " " }, + }, + { + ruleId: "@stylistic/space-in-parens", + severity: 2, + message: "There should be no space before this paren.", + line: 4, + column: 54, + nodeType: "Program", + messageId: "rejectedClosingSpace", + endLine: 4, + endColumn: 59, + fix: { range: [171, 176], text: "" }, + }, + { + ruleId: "@stylistic/padded-blocks", + severity: 2, + message: "Block must be padded by blank lines.", + line: 4, + column: 61, + nodeType: "BlockStatement", + messageId: "alwaysPadBlock", + endLine: 5, + endColumn: 3, + fix: { range: [181, 181], text: "\n" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 2.", + line: 5, + column: 1, + nodeType: "Punctuator", + messageId: "wrongIndentation", + endLine: 5, + endColumn: 3, + fix: { range: [179, 181], text: "" }, + }, + { + ruleId: "@stylistic/brace-style", + severity: 2, + message: "Closing curly brace does not appear on the same line as the subsequent block.", + line: 5, + column: 3, + nodeType: "Punctuator", + messageId: "nextLineClose", + endLine: 5, + endColumn: 4, + fix: { range: [182, 190], text: " " }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 7.", + line: 6, + column: 1, + nodeType: "Keyword", + messageId: "wrongIndentation", + endLine: 6, + endColumn: 8, + fix: { range: [183, 190], text: "" }, + }, + { + ruleId: "@stylistic/padded-blocks", + severity: 2, + message: "Block must be padded by blank lines.", + line: 6, + column: 13, + nodeType: "BlockStatement", + messageId: "alwaysPadBlock", + endLine: 7, + endColumn: 5, + fix: { range: [196, 196], text: "\n" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 2 spaces but found 4.", + line: 7, + column: 1, + nodeType: "Identifier", + messageId: "wrongIndentation", + endLine: 7, + endColumn: 5, + fix: { range: [197, 201], text: " " }, + }, + { + ruleId: "@stylistic/padded-blocks", + severity: 2, + message: "Block must be padded by blank lines.", + line: 7, + column: 30, + nodeType: "BlockStatement", + messageId: "alwaysPadBlock", + endLine: 8, + endColumn: 9, + fix: { range: [235, 235], text: "\n" }, + }, + { + ruleId: "@stylistic/semi", + severity: 2, + message: "Missing semicolon.", + line: 7, + column: 30, + nodeType: "ExpressionStatement", + messageId: "missingSemi", + endLine: 8, + endColumn: 1, + fix: { range: [226, 226], text: ";" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 8.", + line: 8, + column: 1, + nodeType: "Punctuator", + messageId: "wrongIndentation", + endLine: 8, + endColumn: 9, + fix: { range: [227, 235], text: "" }, + }, + { + ruleId: "@stylistic/no-trailing-spaces", + severity: 2, + message: "Trailing spaces not allowed.", + line: 9, + column: 1, + nodeType: "Program", + messageId: "trailingSpace", + endLine: 9, + endColumn: 3, + fix: { range: [237, 239], text: "" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 2.", + line: 10, + column: 1, + nodeType: "Block", + messageId: "wrongIndentation", + endLine: 10, + endColumn: 3, + fix: { range: [240, 242], text: "" }, + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 10, + column: 23, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 10, + endColumn: 25, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [248, 248], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 4.", + line: 11, + column: 1, + nodeType: "Identifier", + messageId: "wrongIndentation", + endLine: 11, + endColumn: 5, + fix: { range: [266, 270], text: "" }, + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 11, + column: 17, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 11, + endColumn: 35, + fix: { range: [282, 300], text: "\"You are lucky 🍀\"" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 2.", + line: 12, + column: 1, + nodeType: "Block", + messageId: "wrongIndentation", + endLine: 12, + endColumn: 3, + fix: { range: [303, 305], text: "" }, + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 12, + column: 23, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 12, + endColumn: 25, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [329, 329], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/no-trailing-spaces", + severity: 2, + message: "Trailing spaces not allowed.", + line: 13, + column: 1, + nodeType: "Program", + messageId: "trailingSpace", + endLine: 13, + endColumn: 3, + fix: { range: [315, 317], text: "" }, + }, + { + ruleId: "@stylistic/eol-last", + severity: 2, + message: "Newline required at end of file but not found.", + line: 13, + column: 3, + nodeType: "Program", + messageId: "missing", + fix: { range: [317, 317], text: "\n" }, + }, +]; + +module.exports = messages; diff --git a/tests/fixtures/common.js b/tests/fixtures/common.js new file mode 100644 index 0000000..4c2f1a6 --- /dev/null +++ b/tests/fixtures/common.js @@ -0,0 +1,13 @@ +if (<%= @success %> ) { + console.log('Success 🎉'); + $('#yeah').html( '<%= j render partial: 'yeah', + locals: { cool: @cool } %>' ); + } + else { + console.log("Sad noises") + } + + <% if you_feel_lucky %> + console.log('You are lucky 🍀'); + <% end %> + \ No newline at end of file diff --git a/tests/fixtures/common.messages.js b/tests/fixtures/common.messages.js new file mode 100644 index 0000000..a8363fc --- /dev/null +++ b/tests/fixtures/common.messages.js @@ -0,0 +1,405 @@ +const messages = [ + { + ruleId: "@stylistic/no-multi-spaces", + severity: 2, + message: "Multiple spaces found before '('.", + line: 1, + column: 3, + nodeType: "Punctuator", + messageId: "multipleSpaces", + endLine: 1, + endColumn: 9, + fix: { range: [2, 8], text: " " }, + }, + { + ruleId: "no-constant-condition", + severity: 2, + message: "Unexpected constant condition.", + line: 1, + column: 30, + nodeType: "ObjectExpression", + messageId: "unexpected", + endLine: 1, + endColumn: 32, + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/no-multi-spaces", + severity: 2, + message: "Multiple spaces found before ')'.", + line: 1, + column: 51, + nodeType: "Punctuator", + messageId: "multipleSpaces", + endLine: 1, + endColumn: 56, + fix: { range: [50, 55], text: " " }, + }, + { + ruleId: "@stylistic/space-in-parens", + severity: 2, + message: "There should be no space before this paren.", + line: 1, + column: 51, + nodeType: "Program", + messageId: "rejectedClosingSpace", + endLine: 1, + endColumn: 56, + fix: { range: [50, 55], text: "" }, + }, + { + ruleId: "@stylistic/padded-blocks", + severity: 2, + message: "Block must be padded by blank lines.", + line: 1, + column: 58, + nodeType: "BlockStatement", + messageId: "alwaysPadBlock", + endLine: 2, + endColumn: 5, + fix: { range: [58, 58], text: "\n" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 2 spaces but found 4.", + line: 2, + column: 1, + nodeType: "Identifier", + messageId: "wrongIndentation", + endLine: 2, + endColumn: 5, + fix: { range: [59, 63], text: " " }, + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 2, + column: 17, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 2, + endColumn: 29, + fix: { range: [75, 87], text: "\"Success 🎉\"" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 2 spaces but found 5.", + line: 3, + column: 1, + nodeType: "Identifier", + messageId: "wrongIndentation", + endLine: 3, + endColumn: 6, + fix: { range: [90, 95], text: " " }, + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 3, + column: 8, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 3, + endColumn: 15, + fix: { range: [97, 104], text: "\"#yeah\"" }, + }, + { + ruleId: "@stylistic/no-multi-spaces", + severity: 2, + message: "Multiple spaces found before ''/* eslint-disable */{}/* eslint-enable */''.", + line: 3, + column: 22, + nodeType: "String", + messageId: "multipleSpaces", + endLine: 3, + endColumn: 24, + fix: { range: [111, 113], text: " " }, + }, + { + ruleId: "@stylistic/space-in-parens", + severity: 2, + message: "There should be no space after this paren.", + line: 3, + column: 22, + nodeType: "Program", + messageId: "rejectedOpeningSpace", + endLine: 3, + endColumn: 24, + fix: { range: [111, 113], text: "" }, + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 3, + column: 24, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 3, + endColumn: 67, + fix: { + range: [113, 156], + text: "\"/* eslint-disable */{}/* eslint-enable */\"", + }, + }, + { + ruleId: "@stylistic/no-multi-spaces", + severity: 2, + message: "Multiple spaces found before ')'.", + line: 3, + column: 67, + nodeType: "Punctuator", + messageId: "multipleSpaces", + endLine: 3, + endColumn: 72, + fix: { range: [156, 161], text: " " }, + }, + { + ruleId: "@stylistic/space-in-parens", + severity: 2, + message: "There should be no space before this paren.", + line: 3, + column: 67, + nodeType: "Program", + messageId: "rejectedClosingSpace", + endLine: 3, + endColumn: 72, + fix: { range: [156, 161], text: "" }, + }, + { + ruleId: "@stylistic/padded-blocks", + severity: 2, + message: "Block must be padded by blank lines.", + line: 3, + column: 74, + nodeType: "BlockStatement", + messageId: "alwaysPadBlock", + endLine: 4, + endColumn: 3, + fix: { range: [166, 166], text: "\n" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 2.", + line: 4, + column: 1, + nodeType: "Punctuator", + messageId: "wrongIndentation", + endLine: 4, + endColumn: 3, + fix: { range: [164, 166], text: "" }, + }, + { + ruleId: "@stylistic/brace-style", + severity: 2, + message: "Closing curly brace does not appear on the same line as the subsequent block.", + line: 4, + column: 3, + nodeType: "Punctuator", + messageId: "nextLineClose", + endLine: 4, + endColumn: 4, + fix: { range: [167, 175], text: " " }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 7.", + line: 5, + column: 1, + nodeType: "Keyword", + messageId: "wrongIndentation", + endLine: 5, + endColumn: 8, + fix: { range: [168, 175], text: "" }, + }, + { + ruleId: "@stylistic/padded-blocks", + severity: 2, + message: "Block must be padded by blank lines.", + line: 5, + column: 13, + nodeType: "BlockStatement", + messageId: "alwaysPadBlock", + endLine: 6, + endColumn: 5, + fix: { range: [181, 181], text: "\n" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 2 spaces but found 4.", + line: 6, + column: 1, + nodeType: "Identifier", + messageId: "wrongIndentation", + endLine: 6, + endColumn: 5, + fix: { range: [182, 186], text: " " }, + }, + { + ruleId: "@stylistic/padded-blocks", + severity: 2, + message: "Block must be padded by blank lines.", + line: 6, + column: 30, + nodeType: "BlockStatement", + messageId: "alwaysPadBlock", + endLine: 7, + endColumn: 9, + fix: { range: [220, 220], text: "\n" }, + }, + { + ruleId: "@stylistic/semi", + severity: 2, + message: "Missing semicolon.", + line: 6, + column: 30, + nodeType: "ExpressionStatement", + messageId: "missingSemi", + endLine: 7, + endColumn: 1, + fix: { range: [211, 211], text: ";" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 8.", + line: 7, + column: 1, + nodeType: "Punctuator", + messageId: "wrongIndentation", + endLine: 7, + endColumn: 9, + fix: { range: [212, 220], text: "" }, + }, + { + ruleId: "@stylistic/no-trailing-spaces", + severity: 2, + message: "Trailing spaces not allowed.", + line: 8, + column: 1, + nodeType: "Program", + messageId: "trailingSpace", + endLine: 8, + endColumn: 3, + fix: { range: [222, 224], text: "" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 2.", + line: 9, + column: 1, + nodeType: "Block", + messageId: "wrongIndentation", + endLine: 9, + endColumn: 3, + fix: { range: [225, 227], text: "" }, + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 9, + column: 23, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 9, + endColumn: 25, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [248, 248], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 4.", + line: 10, + column: 1, + nodeType: "Identifier", + messageId: "wrongIndentation", + endLine: 10, + endColumn: 5, + fix: { range: [269, 273], text: "" }, + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 10, + column: 17, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 10, + endColumn: 35, + fix: { range: [285, 303], text: "\"You are lucky 🍀\"" }, + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 2.", + line: 11, + column: 1, + nodeType: "Block", + messageId: "wrongIndentation", + endLine: 11, + endColumn: 3, + fix: { range: [306, 308], text: "" }, + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 11, + column: 23, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 11, + endColumn: 25, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [329, 329], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/no-trailing-spaces", + severity: 2, + message: "Trailing spaces not allowed.", + line: 12, + column: 1, + nodeType: "Program", + messageId: "trailingSpace", + endLine: 12, + endColumn: 3, + fix: { range: [350, 352], text: "" }, + }, + { + ruleId: "@stylistic/eol-last", + severity: 2, + message: "Newline required at end of file but not found.", + line: 12, + column: 3, + nodeType: "Program", + messageId: "missing", + fix: { range: [352, 352], text: "\n" }, + }, +]; + +module.exports = messages; diff --git a/tests/fixtures/common.pre.js b/tests/fixtures/common.pre.js new file mode 100644 index 0000000..9e41ffc --- /dev/null +++ b/tests/fixtures/common.pre.js @@ -0,0 +1,12 @@ +if (/* eslint-disable */{}/* eslint-enable */ ) { + console.log('Success 🎉'); + $('#yeah').html( '/* eslint-disable */{}/* eslint-enable */' ); + } + else { + console.log("Sad noises") + } + + /* eslint-disable */{}/* eslint-enable */ + console.log('You are lucky 🍀'); + /* eslint-disable */{}/* eslint-enable */ + \ No newline at end of file diff --git a/tests/fixtures/each-do.expected.messages.js b/tests/fixtures/each-do.expected.messages.js new file mode 100644 index 0000000..dc0e209 --- /dev/null +++ b/tests/fixtures/each-do.expected.messages.js @@ -0,0 +1,69 @@ +const messages = [ + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 1, + column: 21, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 1, + endColumn: 23, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [21, 21], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 2, + column: 13, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 2, + endColumn: 23, + fix: { + range: [37, 47], + text: "\"<%= j %>\"", + }, + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 3, + column: 21, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 3, + endColumn: 23, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [134, 134], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/eol-last", + severity: 2, + message: "Newline required at end of file but not found.", + line: 3, + column: 10, + nodeType: "Program", + messageId: "missing", + fix: { range: [72, 72], text: "\n" }, + }, +]; + +module.exports = messages; diff --git a/tests/fixtures/each-do.js b/tests/fixtures/each-do.js new file mode 100644 index 0000000..abacdc6 --- /dev/null +++ b/tests/fixtures/each-do.js @@ -0,0 +1,3 @@ +<% (1..4).each do |j| %> +console.log('<%= j %>'); // a comment +<% end %> \ No newline at end of file diff --git a/tests/fixtures/each-do.messages.js b/tests/fixtures/each-do.messages.js new file mode 100644 index 0000000..d1060e3 --- /dev/null +++ b/tests/fixtures/each-do.messages.js @@ -0,0 +1,69 @@ +const messages = [ + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 1, + column: 21, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 1, + endColumn: 23, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [21, 21], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 2, + column: 13, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 2, + endColumn: 56, + fix: { + range: [54, 97], + text: "\"/* eslint-disable */{}/* eslint-enable */\"", + }, + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 3, + column: 21, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 3, + endColumn: 23, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [134, 134], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/eol-last", + severity: 2, + message: "Newline required at end of file but not found.", + line: 3, + column: 42, + nodeType: "Program", + messageId: "missing", + fix: { range: [154, 154], text: "\n" }, + }, +]; + +module.exports = messages; diff --git a/tests/fixtures/each-do.pre.js b/tests/fixtures/each-do.pre.js new file mode 100644 index 0000000..ca29956 --- /dev/null +++ b/tests/fixtures/each-do.pre.js @@ -0,0 +1,3 @@ +/* eslint-disable */{}/* eslint-enable */ +console.log('/* eslint-disable */{}/* eslint-enable */'); // a comment +/* eslint-disable */{}/* eslint-enable */ \ No newline at end of file diff --git a/tests/fixtures/multi-line.expected.messages.js b/tests/fixtures/multi-line.expected.messages.js new file mode 100644 index 0000000..91db8a6 --- /dev/null +++ b/tests/fixtures/multi-line.expected.messages.js @@ -0,0 +1,81 @@ +const messages = [ + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 4.", + line: 1, + column: 1, + nodeType: "Keyword", + messageId: "wrongIndentation", + endLine: 1, + endColumn: 5, + fix: { range: [0, 4], text: "" }, + }, + { + ruleId: "no-unused-vars", + severity: 1, + message: "'a' is assigned a value but never used.", + line: 1, + column: 11, + nodeType: "Identifier", + messageId: "unusedVar", + endLine: 1, + endColumn: 12, + }, + { + ruleId: "@stylistic/semi", + severity: 2, + message: "Missing semicolon.", + line: 1, + column: 23, + nodeType: "VariableDeclaration", + messageId: "missingSemi", + endLine: 2, + endColumn: 1, + fix: { range: [22, 22], text: ";" }, + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 2, + column: 21, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 2, + endColumn: 23, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [44, 44], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 1.", + line: 5, + column: 1, + nodeType: "Identifier", + messageId: "wrongIndentation", + endLine: 5, + endColumn: 2, + fix: { range: [144, 145], text: "" }, + }, + { + ruleId: "@stylistic/eol-last", + severity: 2, + message: "Newline required at end of file but not found.", + line: 5, + column: 28, + nodeType: "Program", + messageId: "missing", + fix: { range: [171, 171], text: "\n" }, + }, +]; + +module.exports = messages; diff --git a/tests/fixtures/multi-line.js b/tests/fixtures/multi-line.js new file mode 100644 index 0000000..75639fb --- /dev/null +++ b/tests/fixtures/multi-line.js @@ -0,0 +1,5 @@ + const a = "before" +<%= render partial: 'questions/domains/expression', + locals: { a: a, b: b, + c: "c" } %> + console.log("afterwards"); \ No newline at end of file diff --git a/tests/fixtures/multi-line.messages.js b/tests/fixtures/multi-line.messages.js new file mode 100644 index 0000000..46efaeb --- /dev/null +++ b/tests/fixtures/multi-line.messages.js @@ -0,0 +1,81 @@ +const messages = [ + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 4.", + line: 1, + column: 1, + nodeType: "Keyword", + messageId: "wrongIndentation", + endLine: 1, + endColumn: 5, + fix: { range: [0, 4], text: "" }, + }, + { + ruleId: "no-unused-vars", + severity: 1, + message: "'a' is assigned a value but never used.", + line: 1, + column: 11, + nodeType: "Identifier", + messageId: "unusedVar", + endLine: 1, + endColumn: 12, + }, + { + ruleId: "@stylistic/semi", + severity: 2, + message: "Missing semicolon.", + line: 1, + column: 23, + nodeType: "VariableDeclaration", + messageId: "missingSemi", + endLine: 2, + endColumn: 1, + fix: { range: [22, 22], text: ";" }, + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 2, + column: 21, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 2, + endColumn: 23, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [44, 44], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/indent", + severity: 2, + message: "Expected indentation of 0 spaces but found 1.", + line: 3, + column: 1, + nodeType: "Identifier", + messageId: "wrongIndentation", + endLine: 3, + endColumn: 2, + fix: { range: [65, 66], text: "" }, + }, + { + ruleId: "@stylistic/eol-last", + severity: 2, + message: "Newline required at end of file but not found.", + line: 3, + column: 28, + nodeType: "Program", + messageId: "missing", + fix: { range: [92, 92], text: "\n" }, + }, +]; + +module.exports = messages; diff --git a/tests/fixtures/multi-line.pre.js b/tests/fixtures/multi-line.pre.js new file mode 100644 index 0000000..739b9dd --- /dev/null +++ b/tests/fixtures/multi-line.pre.js @@ -0,0 +1,3 @@ + const a = "before" +/* eslint-disable */{}/* eslint-enable */ + console.log("afterwards"); \ No newline at end of file diff --git a/tests/fixtures/multiple-erb-in-one-line.expected.messages.js b/tests/fixtures/multiple-erb-in-one-line.expected.messages.js new file mode 100644 index 0000000..9c46479 --- /dev/null +++ b/tests/fixtures/multiple-erb-in-one-line.expected.messages.js @@ -0,0 +1,215 @@ +const messages = [ + { + ruleId: "@stylistic/max-len", + severity: 2, + message: "This line has a length of 188. Maximum allowed is 100.", + line: 1, + column: 1, + nodeType: "Program", + messageId: "max", + endLine: 1, + endColumn: 112, + }, + { + ruleId: "@stylistic/func-call-spacing", + severity: 2, + message: "Unexpected whitespace between function name and paren.", + line: 1, + column: 9, + nodeType: "CallExpression", + messageId: "unexpectedWhitespace", + fix: { range: [11, 12], text: "" }, + }, + { + ruleId: "@stylistic/function-call-spacing", + severity: 2, + message: "Unexpected whitespace between function name and paren.", + line: 1, + column: 9, + nodeType: "CallExpression", + messageId: "unexpectedWhitespace", + fix: { range: [11, 12], text: "" }, + }, + { + ruleId: "@stylistic/semi-spacing", + severity: 2, + message: "Missing whitespace after semicolon.", + line: 1, + column: 20, + nodeType: "ExpressionStatement", + messageId: "missingWhitespaceAfter", + endLine: 1, + endColumn: 21, + fix: { range: [20, 20], text: " " }, + }, + { + ruleId: "@stylistic/space-before-blocks", + severity: 2, + message: "Missing space before opening brace.", + line: 1, + column: 41, + nodeType: "BlockStatement", + messageId: "missingSpace", + endLine: 1, + endColumn: 43, + fix: { range: [40, 40], text: " " }, + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 1, + column: 41, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 1, + endColumn: 43, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [41, 41], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/max-statements-per-line", + severity: 2, + message: "This line has 3 statements. Maximum allowed is 1.", + line: 1, + column: 45, + nodeType: "ExpressionStatement", + messageId: "exceed", + endLine: 1, + endColumn: 69, + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 1, + column: 57, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 1, + endColumn: 67, + fix: { range: [56, 66], text: "\"whatever\"" }, + }, + { + ruleId: "@stylistic/semi-spacing", + severity: 2, + message: "Missing whitespace after semicolon.", + line: 1, + column: 68, + nodeType: "ExpressionStatement", + messageId: "missingWhitespaceAfter", + endLine: 1, + endColumn: 69, + fix: { range: [68, 68], text: " " }, + }, + { + ruleId: "@stylistic/space-before-blocks", + severity: 2, + message: "Missing space before opening brace.", + line: 1, + column: 89, + nodeType: "BlockStatement", + messageId: "missingSpace", + endLine: 1, + endColumn: 91, + fix: { range: [88, 88], text: " " }, + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 1, + column: 89, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 1, + endColumn: 91, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [106, 106], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 1, + column: 95, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 1, + endColumn: 101, + fix: { range: [94, 100], text: "\"true\"" }, + }, + { + ruleId: "@stylistic/semi-spacing", + severity: 2, + message: "Missing whitespace after semicolon.", + line: 1, + column: 102, + nodeType: "ExpressionStatement", + messageId: "missingWhitespaceAfter", + endLine: 1, + endColumn: 103, + fix: { range: [102, 102], text: " " }, + }, + { + ruleId: "@stylistic/space-before-blocks", + severity: 2, + message: "Missing space before opening brace.", + line: 1, + column: 123, + nodeType: "BlockStatement", + messageId: "missingSpace", + endLine: 1, + endColumn: 125, + fix: { range: [122, 122], text: " " }, + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 1, + column: 123, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 1, + endColumn: 125, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [168, 168], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/eol-last", + severity: 2, + message: "Newline required at end of file but not found.", + line: 1, + column: 112, + nodeType: "Program", + messageId: "missing", + fix: { range: [111, 111], text: "\n" }, + }, +]; + +module.exports = messages; diff --git a/tests/fixtures/multiple-erb-in-one-line.js b/tests/fixtures/multiple-erb-in-one-line.js new file mode 100644 index 0000000..02adfbb --- /dev/null +++ b/tests/fixtures/multiple-erb-in-one-line.js @@ -0,0 +1 @@ +console.log ("Hi ");<%# This is a comment %>console.log('whatever');<% if true %> console.log('true');<% end %> \ No newline at end of file diff --git a/tests/fixtures/multiple-erb-in-one-line.messages.js b/tests/fixtures/multiple-erb-in-one-line.messages.js new file mode 100644 index 0000000..f316af8 --- /dev/null +++ b/tests/fixtures/multiple-erb-in-one-line.messages.js @@ -0,0 +1,215 @@ +const messages = [ + { + ruleId: "@stylistic/max-len", + severity: 2, + message: "This line has a length of 188. Maximum allowed is 100.", + line: 1, + column: 1, + nodeType: "Program", + messageId: "max", + endLine: 1, + endColumn: 189, + }, + { + ruleId: "@stylistic/func-call-spacing", + severity: 2, + message: "Unexpected whitespace between function name and paren.", + line: 1, + column: 9, + nodeType: "CallExpression", + messageId: "unexpectedWhitespace", + fix: { range: [11, 12], text: "" }, + }, + { + ruleId: "@stylistic/function-call-spacing", + severity: 2, + message: "Unexpected whitespace between function name and paren.", + line: 1, + column: 9, + nodeType: "CallExpression", + messageId: "unexpectedWhitespace", + fix: { range: [11, 12], text: "" }, + }, + { + ruleId: "@stylistic/semi-spacing", + severity: 2, + message: "Missing whitespace after semicolon.", + line: 1, + column: 20, + nodeType: "ExpressionStatement", + messageId: "missingWhitespaceAfter", + endLine: 1, + endColumn: 21, + fix: { range: [20, 20], text: " " }, + }, + { + ruleId: "@stylistic/space-before-blocks", + severity: 2, + message: "Missing space before opening brace.", + line: 1, + column: 41, + nodeType: "BlockStatement", + messageId: "missingSpace", + endLine: 1, + endColumn: 43, + fix: { range: [40, 40], text: " " }, + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 1, + column: 41, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 1, + endColumn: 43, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [41, 41], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/max-statements-per-line", + severity: 2, + message: "This line has 3 statements. Maximum allowed is 1.", + line: 1, + column: 62, + nodeType: "ExpressionStatement", + messageId: "exceed", + endLine: 1, + endColumn: 86, + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 1, + column: 74, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 1, + endColumn: 84, + fix: { range: [73, 83], text: "\"whatever\"" }, + }, + { + ruleId: "@stylistic/semi-spacing", + severity: 2, + message: "Missing whitespace after semicolon.", + line: 1, + column: 85, + nodeType: "ExpressionStatement", + messageId: "missingWhitespaceAfter", + endLine: 1, + endColumn: 86, + fix: { range: [85, 85], text: " " }, + }, + { + ruleId: "@stylistic/space-before-blocks", + severity: 2, + message: "Missing space before opening brace.", + line: 1, + column: 106, + nodeType: "BlockStatement", + messageId: "missingSpace", + endLine: 1, + endColumn: 108, + fix: { range: [105, 105], text: " " }, + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 1, + column: 106, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 1, + endColumn: 108, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [106, 106], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 1, + column: 140, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 1, + endColumn: 146, + fix: { range: [139, 145], text: "\"true\"" }, + }, + { + ruleId: "@stylistic/semi-spacing", + severity: 2, + message: "Missing whitespace after semicolon.", + line: 1, + column: 147, + nodeType: "ExpressionStatement", + messageId: "missingWhitespaceAfter", + endLine: 1, + endColumn: 148, + fix: { range: [147, 147], text: " " }, + }, + { + ruleId: "@stylistic/space-before-blocks", + severity: 2, + message: "Missing space before opening brace.", + line: 1, + column: 168, + nodeType: "BlockStatement", + messageId: "missingSpace", + endLine: 1, + endColumn: 170, + fix: { range: [167, 167], text: " " }, + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "no-empty", + severity: 2, + message: "Empty block statement.", + line: 1, + column: 168, + nodeType: "BlockStatement", + messageId: "unexpected", + endLine: 1, + endColumn: 170, + suggestions: [ + { + messageId: "suggestComment", + data: { type: "block" }, + fix: { range: [168, 168], text: " /* empty */ " }, + desc: "Add comment inside empty block statement.", + }, + ], + suppressions: [{ kind: "directive", justification: "" }], + }, + { + ruleId: "@stylistic/eol-last", + severity: 2, + message: "Newline required at end of file but not found.", + line: 1, + column: 189, + nodeType: "Program", + messageId: "missing", + fix: { range: [188, 188], text: "\n" }, + }, +]; + +module.exports = messages; diff --git a/tests/fixtures/multiple-erb-in-one-line.pre.js b/tests/fixtures/multiple-erb-in-one-line.pre.js new file mode 100644 index 0000000..feda253 --- /dev/null +++ b/tests/fixtures/multiple-erb-in-one-line.pre.js @@ -0,0 +1 @@ +console.log ("Hi ");/* eslint-disable */{}/* eslint-enable */console.log('whatever');/* eslint-disable */{}/* eslint-enable */ console.log('true');/* eslint-disable */{}/* eslint-enable */ \ No newline at end of file diff --git a/tests/fixtures/one-liner.expected.messages.js b/tests/fixtures/one-liner.expected.messages.js new file mode 100644 index 0000000..a920e21 --- /dev/null +++ b/tests/fixtures/one-liner.expected.messages.js @@ -0,0 +1,29 @@ +const messages = [ + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 1, + column: 3, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 1, + endColumn: 15, + fix: { + range: [2, 14], + text: "\"#<%= id %>\"", + }, + }, + { + ruleId: "@stylistic/eol-last", + severity: 2, + message: "Newline required at end of file but not found.", + line: 1, + column: 24, + nodeType: "Program", + messageId: "missing", + fix: { range: [23, 23], text: "\n" }, + }, +]; + +module.exports = messages; diff --git a/tests/fixtures/one-liner.js b/tests/fixtures/one-liner.js new file mode 100644 index 0000000..f54653e --- /dev/null +++ b/tests/fixtures/one-liner.js @@ -0,0 +1 @@ +$('#<%= id %>').hide(); \ No newline at end of file diff --git a/tests/fixtures/one-liner.messages.js b/tests/fixtures/one-liner.messages.js new file mode 100644 index 0000000..f51be51 --- /dev/null +++ b/tests/fixtures/one-liner.messages.js @@ -0,0 +1,29 @@ +const messages = [ + { + ruleId: "@stylistic/quotes", + severity: 2, + message: "Strings must use doublequote.", + line: 1, + column: 3, + nodeType: "Literal", + messageId: "wrongQuotes", + endLine: 1, + endColumn: 47, + fix: { + range: [2, 46], + text: "\"#/* eslint-disable */{}/* eslint-enable */\"", + }, + }, + { + ruleId: "@stylistic/eol-last", + severity: 2, + message: "Newline required at end of file but not found.", + line: 1, + column: 56, + nodeType: "Program", + messageId: "missing", + fix: { range: [55, 55], text: "\n" }, + }, +]; + +module.exports = messages; diff --git a/tests/fixtures/one-liner.pre.js b/tests/fixtures/one-liner.pre.js new file mode 100644 index 0000000..5181948 --- /dev/null +++ b/tests/fixtures/one-liner.pre.js @@ -0,0 +1 @@ +$('#/* eslint-disable */{}/* eslint-enable */').hide(); \ No newline at end of file diff --git a/tests/postprocess.js b/tests/postprocess.js new file mode 100644 index 0000000..0484cbf --- /dev/null +++ b/tests/postprocess.js @@ -0,0 +1,41 @@ +const fs = require("fs"); + +const assert = require("chai").assert; +const pre = require("../lib/preprocess.js"); +const post = require("../lib/postprocess.js"); +const cache = require("../lib/cache.js"); + +describe("postprocess", () => { + it("deletes file from cache after postprocessing", () => { + const text = `console.log("Hello world!");`; + const name = "testfile.js"; + + pre(text, name); + assert.exists(cache.get(name)); + assert.isNotEmpty(cache.get(name)); + + post([[]], name); + assert.isUndefined(cache.get(name)); + }); + + const mapFiles = [ + "one-liner", + "common", + "each-do", + "multi-line", + "multiple-erb-in-one-line", + ]; + mapFiles.forEach((name) => { + it(`correctly maps location from offset map on ${name}.js`, () => { + const filename = `tests/fixtures/${name}.js`; + const text = fs.readFileSync(filename, "utf-8"); + pre(text, filename); + + const esLintMessages = require(`../tests/fixtures/${name}.messages.js`); + + const finalMessages = post([esLintMessages], filename); + const expectedMessages = require(`../tests/fixtures/${name}.expected.messages.js`); + assert.deepEqual(expectedMessages, finalMessages); + }); + }); +}); diff --git a/tests/preprocess.js b/tests/preprocess.js new file mode 100644 index 0000000..e3cc801 --- /dev/null +++ b/tests/preprocess.js @@ -0,0 +1,146 @@ +const fs = require("fs"); + +const assert = require("chai").assert; +const p = require("../lib/preprocess.js"); +const cache = require("../lib/cache.js"); + +describe("preprocess", () => { + it("does not crash", () => { + p("Hello, world!"); + }); + + it("does not crash on empty string", () => { + p(""); + }); + + it("returns an array with just one element", () => { + const res = p("Hello, world!"); + assert.isArray(res); + assert.lengthOf(res, 1); + }); + + it("ignores normal text", () => { + const res = p("Hello, world!")[0]; + assert.equal(res, "Hello, world!"); + }); + + const replaceStringFiles = [ + "one-liner", + "common", + "each-do", + "multi-line", + "multiple-erb-in-one-line", + ]; + replaceStringFiles.forEach((name) => { + it(`replaces ruby with dummy string in "${name}.js"`, () => { + const text = fs.readFileSync(`tests/fixtures/${name}.js`, "utf-8"); + const textLintableExpected = fs.readFileSync(`tests/fixtures/${name}.pre.js`, "utf-8"); + + const textLintable = p(text)[0]; + assert.equal(textLintable, textLintableExpected); + }); + }); + + const offsets = [ + { + name: "one-liner", + expected: { + lineOffsetLookup: new Map([ + [1, new Map([ + [45, { lineOffset: 0, columnOffset: -32 }], + ])], + ]), + offsetLookup: new Map([ + [45, { lineOffset: 0, columnOffset: -32 }], + ]), + }, + }, + { + name: "multi-line", + expected: { + lineOffsetLookup: new Map([ + [2, new Map([ + [64, { lineOffset: 2, columnOffset: -7 }], + ])], + ]), + offsetLookup: new Map([ + [64, { lineOffset: 2, columnOffset: -7 }], + ]), + }, + }, + { + name: "common", + expected: { + lineOffsetLookup: new Map([ + [1, new Map([ + [50, { lineOffset: 0, columnOffset: -26 }], + ])], + [3, new Map([ + [155, { lineOffset: 1, columnOffset: -13 }], + ])], + [9, new Map([ + [268, { lineOffset: 1, columnOffset: -18 }], + ])], + [11, new Map([ + [349, { lineOffset: 1, columnOffset: -32 }], + ])], + ]), + offsetLookup: new Map([ + [50, { lineOffset: 0, columnOffset: -26 }], + [155, { lineOffset: 1, columnOffset: -13 }], + [268, { lineOffset: 1, columnOffset: -18 }], + [349, { lineOffset: 1, columnOffset: -32 }], + ]), + }, + }, + { + name: "each-do", + expected: { + lineOffsetLookup: new Map([ + [1, new Map([ + [41, { lineOffset: 0, columnOffset: -17 }], + ])], + [2, new Map([ + [96, { lineOffset: 0, columnOffset: -33 }], + ])], + [3, new Map([ + [154, { lineOffset: 0, columnOffset: -32 }], + ])], + ]), + offsetLookup: new Map([ + [41, { lineOffset: 0, columnOffset: -17 }], + [96, { lineOffset: 0, columnOffset: -33 }], + [154, { lineOffset: 0, columnOffset: -32 }], + ]), + }, + }, + { + // This tests that column offsets are correctly calculated for multiple + // ERB tags on the same line. + name: "multiple-erb-in-one-line", + expected: { + lineOffsetLookup: new Map([ + [1, new Map([ + [61, { lineOffset: 0, columnOffset: -17 }], + [126, { lineOffset: 0, columnOffset: -45 }], + [188, { lineOffset: 0, columnOffset: -77 }], + ])], + ]), + offsetLookup: new Map([ + [61, { lineOffset: 0, columnOffset: -17 }], + [126, { lineOffset: 0, columnOffset: -45 }], + [188, { lineOffset: 0, columnOffset: -77 }], + ]), + }, + }, + ]; + offsets.forEach(({ name, expected }) => { + it(`correctly constructs offset map for "${name}.js`, () => { + const text = fs.readFileSync(`tests/fixtures/${name}.js`, "utf-8"); + p(text, name); + const offsetMap = cache.get(name).offsetMap; + assert.deepEqual(offsetMap.lineOffsetLookup, expected.lineOffsetLookup); + assert.deepEqual(offsetMap.offsetLookup, expected.offsetLookup); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index 1567604..6384276 100644 --- a/yarn.lock +++ b/yarn.lock @@ -198,18 +198,31 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -220,11 +233,21 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -233,19 +256,49 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.2: +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -chalk@^4.0.0: +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +chai@^4.3.10: + version "4.3.10" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.10.tgz#d784cec635e3b7e2ffb66446a63b4e33bd390384" + integrity sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" + pathval "^1.1.1" + type-detect "^4.0.8" + +chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -253,6 +306,37 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +check-error@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" + integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== + dependencies: + get-func-name "^2.0.2" + +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -279,18 +363,35 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: +debug@4.3.4, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +deep-eql@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -305,7 +406,17 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -escape-string-regexp@^4.0.0: +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== @@ -447,7 +558,7 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -find-up@^5.0.0: +find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== @@ -464,6 +575,11 @@ flat-cache@^3.0.4: keyv "^4.5.3" rimraf "^3.0.2" +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + flatted@^3.2.9: version "3.2.9" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" @@ -474,7 +590,22 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -glob-parent@^5.1.2: +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.1, get-func-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== + +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -488,6 +619,18 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.1.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -529,6 +672,11 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + ignore@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" @@ -560,12 +708,24 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -582,12 +742,22 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -js-yaml@^4.1.0: +js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -636,6 +806,21 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +loupe@^2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" + integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== + dependencies: + get-func-name "^2.0.1" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -656,23 +841,72 @@ micromatch@^4.0.4: braces "^3.0.2" picomatch "^2.3.1" -minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" +mocha@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" + integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -733,7 +967,12 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -picomatch@^2.3.1: +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -753,6 +992,25 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -777,6 +1035,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" @@ -784,6 +1047,13 @@ semver@^7.5.4: dependencies: lru-cache "^6.0.0" +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -801,18 +1071,34 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -strip-ansi@^6.0.1: +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" -strip-json-comments@^3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -844,6 +1130,11 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-detect@^4.0.0, type-detect@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" @@ -863,16 +1154,68 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" From 88eb327d194c9f0be131adb72aadd4dfd324aa7d Mon Sep 17 00:00:00 2001 From: Splines <37160523+Splines@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:48:10 +0100 Subject: [PATCH 2/4] Add VSCode settings.json suggestion & improve Readme (#4) --- README.md | 53 +++++++++++++++++++++++++++++++++++++++++++++---- tests/README.md | 15 +++++--------- 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 03d02c2..6befe17 100644 --- a/README.md +++ b/README.md @@ -43,14 +43,59 @@ module.exports = { }; ``` +If you're wondering what a good starting point for your own `.eslintrc.js` file might be, you can use the config from [here](https://github.com/Splines/eslint-plugin-erb/tree/main/tests#environment). + ## Editor Integrations The [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) for VSCode has built-in support for the ERB processor once you've configured it in your `.eslintrc.js` file as shown above. +If you're using VSCode, you may find this `settings.json` options useful: +```jsonc +{ + ////////////////////////////////////// + // JS (ESLint) + ////////////////////////////////////// + // https://eslint.style/guide/faq#how-to-auto-format-on-save + // https://github.com/microsoft/vscode-eslint#settings-options + "editor.formatOnSave": true, + "eslint.format.enable": true, + "[javascript]": { + "editor.formatOnSave": false, // to avoid formatting twice (ESLint + VSCode) + "editor.defaultFormatter": "dbaeumer.vscode-eslint" // use ESLint plugin + }, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true // Auto-fix ESLint errors on save + }, + // this disables VSCode built-int formatter (instead we want to use ESLint) + "javascript.validate.enable": false, + ////////////////////////////////////// + // Files + ////////////////////////////////////// + "files.exclude": { + "node_modules/": false, + }, + "files.associations": { + "*.js.erb": "javascript" + }, +} +``` + + +## Limitations +- Does not account for code indentation inside `if/else` ERB statements, e.g. +this snippet -## TODO +```js +<% if you_feel_lucky %> + console.log("You are lucky 🍀"); +<% end %> +``` +will be autofixed to +```js +<% if you_feel_lucky %> +console.log("You are lucky 🍀"); +<% end %> +``` -- [ ] Add tests -- [ ] Improve in-line documentation -- [ ] Add guide on how to use +- No support for ESLint suggestions (but full support for Autofixes as shown in the GIF above) diff --git a/tests/README.md b/tests/README.md index 12ca7e9..be5427e 100644 --- a/tests/README.md +++ b/tests/README.md @@ -13,7 +13,7 @@ npm test For reproduction, this is the ESLint configuration file used to generate the input messages for testing (see the `tests/fixtures/` folder. The files were manually renamed to end with `.js.erb` during this process. ```js -//.eslintrc.js +// .eslintrc.js // Starting with v9, this config will be deprecated in favor of the new // configuration files [1]. @stylistic is already ready for the new "flat config", // when it's time, copy the new config from [2]. @@ -42,19 +42,14 @@ module.exports = { "jquery": true, "es6": true }, - "extends": [ - "eslint:recommended", - "plugin:@stylistic/all-extends" - ], "plugins": [ "@stylistic", "erb" ], - "overrides": [ - { - "files": ["*.js.erb"], - "processor": "erb/erbProcessor" - } + "extends": [ + "eslint:recommended", + "plugin:@stylistic/all-extends", + "plugin:erb/recommended" ], "rules": { "no-unused-vars": "warn", From fccaf98465e42fe521f2c7a463de9938fbade38f Mon Sep 17 00:00:00 2001 From: Splines <37160523+Splines@users.noreply.github.com> Date: Sat, 2 Dec 2023 00:40:11 +0100 Subject: [PATCH 3/4] Improve npm publishing (#5) * Change when to run test CI/CD * Add scripts to package.json and files to include * Add some notes for dev guidelines * Add whats included script --- .github/workflows/test.yml | 2 +- DEV.md | 25 +++++++++++++++++++++++++ package.json | 13 +++++++++++-- 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 DEV.md diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 39276d4..c2f74ec 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,7 +2,7 @@ name: Tests on: push: - branches: [main, dev] + branches: [main] pull_request: types: [opened, reopened, synchronize, ready_for_review] diff --git a/DEV.md b/DEV.md new file mode 100644 index 0000000..3ea87eb --- /dev/null +++ b/DEV.md @@ -0,0 +1,25 @@ +# Some developer guidelines + + +## Merge strategies + +- Feature branches to `dev`: squash commit +- Continuous Release from `dev` to `main`: standard merge commit +- Hotfixes: branch off `main`, merge PR into `main` via squash commit, then merge back `main` to `dev` via standard merge commit. + + +## Create a new release (and publish to npm) + +As this is only a small project, we haven't automated publishing to the NPM registry yet and instead rely on the following manual workflow. + +- Make sure the tests pass locally: `npm test` ✔ +- Make another commit on the `dev` branch bumping the npm version in the `package.json`. For that, use: +```sh +npm run bump-version -- [ | major | minor | patch] +``` +- Once the `dev` branch is ready, open a PR (Pull request) called "Continuous Release " and give it the "release" label. Merge this PR into `main`. +- Create a new release via the GitHub UI and assign a new tag alongside that. +- Fetch the tag locally (`git fetch`) and publish to npm via `npm run publish-final`. You probably have to login to npm first (`npm login`). +- Enjoy ✌ Check that the release is available [here on npm](https://www.npmjs.com/package/eslint-plugin-erb). + + diff --git a/package.json b/package.json index 410c210..628aa73 100644 --- a/package.json +++ b/package.json @@ -14,13 +14,19 @@ "keywords": [ "eslint", "eslintplugin", + "eslint-processor", "erb", "ruby", + "embedded ruby", "javascript", "lint", "linter" ], "main": "index.js", + "files": [ + "index.js", + "lib" + ], "devDependencies": { "@stylistic/eslint-plugin": "^1.3.3", "chai": "^4.3.10", @@ -28,6 +34,9 @@ "mocha": "^10.2.0" }, "scripts": { - "test": "mocha" + "test": "mocha", + "whats-included": "npm pack --dry-run", + "bump-version": "npm run test && npm version --no-git-tag-version", + "publish-final": "npm run test && npm publish" } -} +} \ No newline at end of file From f26939d038d7810f82805ce8413a07b5d92dcb21 Mon Sep 17 00:00:00 2001 From: Splines Date: Sat, 2 Dec 2023 00:43:42 +0100 Subject: [PATCH 4/4] Bump package.json version to 1.1.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 628aa73..c25fe00 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-erb", - "version": "1.0.2-0", + "version": "1.1.0", "description": "An ESLint plugin to lint JavaScript in ERB files (.js.erb)", "license": "MIT", "author": { @@ -39,4 +39,4 @@ "bump-version": "npm run test && npm version --no-git-tag-version", "publish-final": "npm run test && npm publish" } -} \ No newline at end of file +}