Socket
Socket
Sign inDemoInstall

eslint-plugin-svelte3

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-svelte3 - npm Package Compare versions

Comparing version 2.7.2 to 2.7.3

4

CHANGELOG.md

@@ -0,1 +1,5 @@

# 2.7.3
- Fix mishandling of blocks whose last line consists of only the expected indentation
# 2.7.2

@@ -2,0 +6,0 @@

265

index.js
'use strict';
const blocks = new Map();
const new_block = () => ({ transformed_code: '', line_offsets: null, translations: new Map() });
let custom_compiler, default_compiler, compiler_options, messages, ignore_warnings, ignore_styles, named_blocks, var_names;
// get the total length, number of lines, and length of the last line of a string

@@ -49,2 +45,5 @@ const get_offsets = str => {

total_offsets.push(total_offsets[total_offsets.length - 1] + offsets[offsets.length - 1]);
if (i >= str.length) {
break;
}
}

@@ -56,76 +55,16 @@ dedented += str[i];

// transform a linting message according to the module/instance script info we've gathered
const transform_message = ({ transformed_code }, { unoffsets, dedent, offsets, range }, message) => {
// strip out the start and end of the fix if they are not actually changes
if (message.fix) {
while (message.fix.range[0] < message.fix.range[1] && transformed_code[message.fix.range[0]] === message.fix.text[0]) {
message.fix.range[0]++;
message.fix.text = message.fix.text.slice(1);
// get character offsets of each line in a string
const get_line_offsets = str => {
const offsets = [-1];
for (let i = 0; i < str.length; i++) {
if (str[i] === '\n') {
offsets.push(i);
}
while (message.fix.range[0] < message.fix.range[1] && transformed_code[message.fix.range[1] - 1] === message.fix.text[message.fix.text.length - 1]) {
message.fix.range[1]--;
message.fix.text = message.fix.text.slice(0, -1);
}
}
// shift position reference backward according to unoffsets
{
const { length, lines, last } = unoffsets;
if (message.line === lines) {
message.column -= last;
}
if (message.endColumn && message.endLine === lines) {
message.endColumn -= last;
}
message.line -= lines - 1;
if (message.endLine) {
message.endLine -= lines - 1;
}
if (message.fix) {
message.fix.range[0] -= length;
message.fix.range[1] -= length;
}
}
// adjust position reference according to the previous dedenting
{
const { offsets, total_offsets } = dedent;
message.column += offsets[message.line - 1];
if (message.endColumn) {
message.endColumn += offsets[message.endLine - 1];
}
if (message.fix) {
message.fix.range[0] += total_offsets[message.line];
message.fix.range[1] += total_offsets[message.line];
}
}
// shift position reference forward according to offsets
{
const { length, lines, last } = offsets;
if (message.line === 1) {
message.column += last;
}
if (message.endColumn && message.endLine === 1) {
message.endColumn += last;
}
message.line += lines - 1;
if (message.endLine) {
message.endLine += lines - 1;
}
if (message.fix) {
message.fix.range[0] += length;
message.fix.range[1] += length;
}
}
// make sure the fix doesn't include anything outside the range of the script
if (message.fix) {
if (message.fix.range[0] < range[0]) {
message.fix.text = message.fix.text.slice(range[0] - message.fix.range[0]);
message.fix.range[0] = range[0];
}
if (message.fix.range[1] > range[1]) {
message.fix.text = message.fix.text.slice(0, range[1] - message.fix.range[1]);
message.fix.range[1] = range[1];
}
}
return offsets;
};
// return a new block
const new_block = () => ({ transformed_code: '', line_offsets: null, translations: new Map() });
// get translation info and include the processed scripts in this block's transformed_code

@@ -147,2 +86,37 @@ const get_translation = (text, block, node, options = {}) => {

const processor_options = {};
// find Linter instance
const linter_path = Object.keys(require.cache).find(path => path.endsWith('/eslint/lib/linter/linter.js') || path.endsWith('\\eslint\\lib\\linter\\linter.js'));
if (!linter_path) {
throw new Error('Could not find ESLint Linter in require cache');
}
const { Linter } = require(linter_path);
// patch Linter#verify
const { verify } = Linter.prototype;
Linter.prototype.verify = function(code, config, options) {
// fetch settings
const settings = config && (typeof config.extractConfig === 'function' ? config.extractConfig(options.filename) : config).settings || {};
processor_options.custom_compiler = settings['svelte3/compiler'];
processor_options.ignore_warnings = settings['svelte3/ignore-warnings'];
processor_options.ignore_styles = settings['svelte3/ignore-styles'];
processor_options.compiler_options = settings['svelte3/compiler-options'];
processor_options.named_blocks = settings['svelte3/named-blocks'];
// call original Linter#verify
return verify.call(this, code, config, options);
};
let state;
const reset = () => {
state = {
messages: null,
var_names: null,
blocks: new Map(),
};
};
reset();
let default_compiler;
// find the contextual name or names described by a particular node in the AST

@@ -168,4 +142,4 @@ const contextual_names = [];

const preprocess = text => {
const compiler = custom_compiler || default_compiler || (default_compiler = require('svelte/compiler'));
if (ignore_styles) {
const compiler = processor_options.custom_compiler || default_compiler || (default_compiler = require('svelte/compiler'));
if (processor_options.ignore_styles) {
// wipe the appropriate <style> tags in the file

@@ -182,3 +156,3 @@ text = text.replace(/<style(\s[^]*?)?>[^]*?<\/style>/gi, (match, attributes = '') => {

});
return ignore_styles(attrs) ? match.replace(/\S/g, ' ') : match;
return processor_options.ignore_styles(attrs) ? match.replace(/\S/g, ' ') : match;
});

@@ -189,6 +163,6 @@ }

try {
result = compiler.compile(text, { generate: false, ...compiler_options });
result = compiler.compile(text, { generate: false, ...processor_options.compiler_options });
} catch ({ name, message, start, end }) {
// convert the error to a linting message, store it, and return
messages = [
state.messages = [
{

@@ -208,6 +182,6 @@ ruleId: name,

const references_and_reassignments = `{${vars.filter(v => v.referenced).map(v => v.name)};${vars.filter(v => v.reassigned || v.export_name).map(v => v.name + '=0')}}`;
var_names = new Set(vars.map(v => v.name));
state.var_names = new Set(vars.map(v => v.name));
// convert warnings to linting messages
messages = (ignore_warnings ? warnings.filter(warning => !ignore_warnings(warning)) : warnings).map(({ code, message, start, end }) => ({
state.messages = (processor_options.ignore_warnings ? warnings.filter(warning => !processor_options.ignore_warnings(warning)) : warnings).map(({ code, message, start, end }) => ({
ruleId: code,

@@ -227,3 +201,3 @@ severity: 1,

const block = new_block();
blocks.set('module.js', block);
state.blocks.set('module.js', block);

@@ -242,3 +216,3 @@ get_translation(text, block, ast.module.content);

const block = new_block();
blocks.set('instance.js', block);
state.blocks.set('instance.js', block);

@@ -255,3 +229,3 @@ block.transformed_code = vars.filter(v => v.injected || v.module).map(v => `let ${v.name};`).join('');

const block = new_block();
blocks.set('template.js', block);
state.blocks.set('template.js', block);

@@ -304,5 +278,79 @@ block.transformed_code = vars.map(v => `let ${v.name};`).join('');

// return processed string
return [...blocks].map(([filename, { transformed_code: text }]) => named_blocks ? { text, filename } : text);
return [...state.blocks].map(([filename, { transformed_code: text }]) => processor_options.named_blocks ? { text, filename } : text);
};
// transform a linting message according to the module/instance script info we've gathered
const transform_message = ({ transformed_code }, { unoffsets, dedent, offsets, range }, message) => {
// strip out the start and end of the fix if they are not actually changes
if (message.fix) {
while (message.fix.range[0] < message.fix.range[1] && transformed_code[message.fix.range[0]] === message.fix.text[0]) {
message.fix.range[0]++;
message.fix.text = message.fix.text.slice(1);
}
while (message.fix.range[0] < message.fix.range[1] && transformed_code[message.fix.range[1] - 1] === message.fix.text[message.fix.text.length - 1]) {
message.fix.range[1]--;
message.fix.text = message.fix.text.slice(0, -1);
}
}
// shift position reference backward according to unoffsets
{
const { length, lines, last } = unoffsets;
if (message.line === lines) {
message.column -= last;
}
if (message.endColumn && message.endLine === lines) {
message.endColumn -= last;
}
message.line -= lines - 1;
if (message.endLine) {
message.endLine -= lines - 1;
}
if (message.fix) {
message.fix.range[0] -= length;
message.fix.range[1] -= length;
}
}
// adjust position reference according to the previous dedenting
{
const { offsets, total_offsets } = dedent;
message.column += offsets[message.line - 1];
if (message.endColumn) {
message.endColumn += offsets[message.endLine - 1];
}
if (message.fix) {
message.fix.range[0] += total_offsets[message.line];
message.fix.range[1] += total_offsets[message.line];
}
}
// shift position reference forward according to offsets
{
const { length, lines, last } = offsets;
if (message.line === 1) {
message.column += last;
}
if (message.endColumn && message.endLine === 1) {
message.endColumn += last;
}
message.line += lines - 1;
if (message.endLine) {
message.endLine += lines - 1;
}
if (message.fix) {
message.fix.range[0] += length;
message.fix.range[1] += length;
}
}
// make sure the fix doesn't include anything outside the range of the script
if (message.fix) {
if (message.fix.range[0] < range[0]) {
message.fix.text = message.fix.text.slice(range[0] - message.fix.range[0]);
message.fix.range[0] = range[0];
}
if (message.fix.range[1] > range[1]) {
message.fix.text = message.fix.text.slice(0, range[1] - message.fix.range[1]);
message.fix.range[1] = range[1];
}
}
};
// extract the string referenced by a message

@@ -312,10 +360,5 @@ const get_referenced_string = (block, message) => {

if (!block.line_offsets) {
block.line_offsets = [-1, -1];
for (let i = 0; i < block.transformed_code.length; i++) {
if (block.transformed_code[i] === '\n') {
block.line_offsets.push(i);
}
}
block.line_offsets = get_line_offsets(block.transformed_code);
}
return block.transformed_code.slice(block.line_offsets[message.line] + message.column, block.line_offsets[message.endLine] + message.endColumn);
return block.transformed_code.slice(block.line_offsets[message.line - 1] + message.column, block.line_offsets[message.endLine - 1] + message.endColumn);
}

@@ -335,3 +378,3 @@ };

case 'no-restricted-syntax': return message.nodeType !== 'LabeledStatement' || get_identifier(get_referenced_string(block, message)) !== '$';
case 'no-self-assign': return !var_names.has(get_identifier(get_referenced_string(block, message)));
case 'no-self-assign': return !state.var_names.has(get_identifier(get_referenced_string(block, message)));
case 'no-unused-labels': return get_referenced_string(block, message) !== '$';

@@ -346,3 +389,3 @@ case 'quotes': return !translation.options.in_quoted_attribute;

// filter messages and fix their offsets
const blocks_array = [...blocks.values()];
const blocks_array = [...state.blocks.values()];
for (let i = 0; i < blocks_messages.length; i++) {

@@ -355,3 +398,3 @@ const block = blocks_array[i];

transform_message(block, translation, message);
messages.push(message);
state.messages.push(message);
}

@@ -362,33 +405,9 @@ }

// sort messages and return
const sorted_messages = messages.sort((a, b) => a.line - b.line || a.column - b.column);
blocks.clear();
custom_compiler = ignore_warnings = ignore_styles = compiler_options = messages = var_names = null;
const sorted_messages = state.messages.sort((a, b) => a.line - b.line || a.column - b.column);
reset();
return sorted_messages;
};
/// PATCH THE LINTER - HACK TO GET ACCESS TO SETTINGS ///
var index = { processors: { svelte3: { preprocess, postprocess, supportsAutofix: true } } };
// find Linter instance
const linter_path = Object.keys(require.cache).find(path => path.endsWith('/eslint/lib/linter/linter.js') || path.endsWith('\\eslint\\lib\\linter\\linter.js'));
if (!linter_path) {
throw new Error('Could not find ESLint Linter in require cache');
}
const { Linter } = require(linter_path);
// patch Linter#verify
const { verify } = Linter.prototype;
Linter.prototype.verify = function(code, config, options) {
// fetch settings
const settings = config && (typeof config.extractConfig === 'function' ? config.extractConfig(options.filename) : config).settings || {};
custom_compiler = settings['svelte3/compiler'];
ignore_warnings = settings['svelte3/ignore-warnings'];
ignore_styles = settings['svelte3/ignore-styles'];
compiler_options = settings['svelte3/compiler-options'];
named_blocks = settings['svelte3/named-blocks'];
// call original Linter#verify
return verify.call(this, code, config, options);
};
/// EXPORT THE PROCESSOR ///
exports.processors = { svelte3: { preprocess, postprocess, supportsAutofix: true } };
module.exports = index;
{
"name": "eslint-plugin-svelte3",
"version": "2.7.2",
"version": "2.7.3",
"description": "An ESLint plugin for Svelte v3 components.",

@@ -29,8 +29,11 @@ "keywords": [

"scripts": {
"test": "node test"
"build": "rollup -c",
"dev": "rollup -cw",
"test": "npm run build && node test"
},
"devDependencies": {
"eslint": ">=6.0.0",
"rollup": "^1",
"svelte": "^3.2.0"
}
}

@@ -93,3 +93,3 @@ # eslint-plugin-svelte3

When an [ESLint processor](https://eslint.org/docs/user-guide/configuring#specifying-processor) processes a file, it is able to output named code blocks, which can each have their own linting configuration. When this setting is enabled, the code extracted from `<script context='module>` tag, the `<script>` tag, and the template are respectively given the block names `module.js`, `instance.js`, and `template.js`.
When an [ESLint processor](https://eslint.org/docs/user-guide/configuring#specifying-processor) processes a file, it is able to output named code blocks, which can each have their own linting configuration. When this setting is enabled, the code extracted from `<script context='module'>` tag, the `<script>` tag, and the template are respectively given the block names `module.js`, `instance.js`, and `template.js`.

@@ -96,0 +96,0 @@ This means that to override linting rules in Svelte components, you'd instead have to target `**/*.svelte/*.js`. But it also means that you can define an override targeting `**/*.svelte/*_template.js` for example, and that configuration will only apply to linting done on the templates in Svelte components.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc