Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript? #68

Closed
abalmos opened this issue Jul 9, 2020 · 19 comments · Fixed by #83
Closed

Typescript? #68

abalmos opened this issue Jul 9, 2020 · 19 comments · Fixed by #83
Labels
question Further information is requested

Comments

@abalmos
Copy link

abalmos commented Jul 9, 2020

I hope this isn't too much noise--I'm having some trouble stitching together Svelte Typescript support and I can not tell if it is a configuration issue or if I'm just ahead of support. Should this plugin be compatible with Typescript?

I've tried the below eslintrc.js (and others). It appears eslint is still trying to parse the <script lang="ts> block with a Javascript parser.

>>module.exports = {                                                               
    root: true,                                                                    
    parser: '@typescript-eslint/parser',                                           
    parserOptions: {                                                               
      ecmaVersion: 2018,                                                           
    },                                                                           
    env: {                                                                         
      node: true,                                                                  
    },                                                                             
    plugins: ['svelte3', '@typescript-eslint'],                                    
    extends: ['eslint:recommended'],                                               
    overrides: [                                                                   
      {                                                                            
        files: ['*.svelte'],                                                       
        processor: 'svelte3/svelte3',                                              
      },                                                                           
      {                                                                            
        files: ['**/*.ts', '**/*.svelte'],                                         
        env: {                                                                     
          node: false,                                                             
          es6: true,                                                               
        },                                                                         
        extends: [                                                                 
          'plugin:@typescript-eslint/eslint-recommended',                          
          'plugin:@typescript-eslint/recommended',                                 
        ],                                                                         
      },                                                                           
    ],                                                                             
  };     

If support is not ready, do you have an pointers on how I might try and contribute that?

@Conduitry Conduitry added the question Further information is requested label Jul 9, 2020
@Conduitry
Copy link
Member

This is not supported currently, and is blocked by support for preprocessors (#10) at the very least. I don't know what else might be involved beyond that.

@NicoCevallos
Copy link

@Conduitry could you review this?
#62

@NicoCevallos
Copy link

@abalmos check this, maybe would be useful for your case
https://svelte.dev/blog/svelte-and-typescript

@gterras
Copy link

gterras commented Oct 17, 2020

Is there any news on this? If I understand correctly there is currently no way to get TS and es-lint working together in svelte files?

@popoleeMaster
Copy link

So I currently setup

.eslintrc

{
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended"
    ],
    "parserOptions": {
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "plugins": [
        "@typescript-eslint",
        "svelte3"
    ],
    "overrides": [
        {
            "files": ["*.svelte"],
            "processor": "svelte3/svelte3"
        }
    ],
    "rules": {
        "semi": [
            "error",
            "always"
        ]
    },
	"settings": {
		"import/core-modules": ["svelte"]
	}
}

in .vscode

  "eslint.validate": [
    "typescript",
    "svelte",
  ],

problem is, If I add eslint to .svelte I get only javascript linting, and there is no way (to me at the moment) to make it work with typescript.

Is it correct , or is there a trick to have linted typescript svelte file ?

@mantismamita
Copy link

Hello, has there been any movement on this issue? We would very much like to use eslint with typescript in our project.

@IgnusG
Copy link

IgnusG commented Nov 20, 2020

We are using the following setup to allow eslint in typescript svelte projects (maybe it helps - if I remember correctly this setup allows for most typescript rules in svelte - check the rule section for which ones don't work):

.eslintrc.js
/* eslint-disable */
const path = require('path');
const eslintSveltePreprocess = require("eslint-svelte3-preprocess");
const svelteConfig = require("./svelte.config");
module.exports = {
  parser: "@typescript-eslint/parser",
  extends: [
    "plugin:import/errors",
    "plugin:import/warnings",
    "plugin:import/typescript",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking",
    "prettier"
  ],
  parserOptions: {
    ecmaVersion: 2020,
    tsconfigRootDir: __dirname,
    project: ['./tsconfig.json'],
    extraFileExtensions: [".svelte"]
	},
  plugins: [
    "@typescript-eslint",
    "svelte3"
  ],
  globals: {
    "process": true
  },
  rules: {
    // Checked by type checker with inference
    "@typescript-eslint/explicit-function-return-type": "off",
    // Conflicts with type inference of svelte's typescript preprocessor
    "@typescript-eslint/no-inferrable-types": "off",
    // Ignore _ (used for required but ignored parameters)
    "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
    // Used to import static file paths then querried by getURL
    "@typescript-eslint/no-var-requires": "off",
    // We use TS namespaces to extend the window object inline in some cases
    "@typescript-eslint/no-namespace": "off",
    "import/order": ["error", {
      alphabetize: {
        order: 'asc',
      },
      "newlines-between": "always-and-inside-groups"
    }],
  },
  overrides: [
    {
      "files": ["*.js"],
      "rules": {
        "@typescript-eslint/explicit-function-return-type": 0,
        "@typescript-eslint/no-empty-function": 0,
        "@typescript-eslint/no-use-before-define": 0,
        "@typescript-eslint/no-var-requires": 0 // works only in ts files
      }
    },
    {
      "files": ["*.svelte"],
      "processor": "svelte3/svelte3",
      "rules": {
        // See for details:
        // https://github.com/sveltejs/eslint-plugin-svelte3/blob/v2.7.3/OTHER_PLUGINS.md
        "import/first": "off",
        "import/no-duplicates": "off",
        "import/no-mutable-exports": "off"
      }
    },
    {
      "files": ["*.test.ts"],
      "rules": {
        // Conflicts with the mocking mechanism (imports are top level only but mocks are hoisted)
        "@typescript-eslint/no-var-requires": "off"
      }
    }
  ],
  settings: {
    // Preprocess typescript eslint - See https://github.com/NicoCevallos/eslint-svelte3-preprocess
    "svelte3/preprocess": eslintSveltePreprocess(svelteConfig.preprocess),
    "import/resolver": {
      "webpack": {
        config: path.resolve(__dirname, 'webpack', 'webpack.base.js')
      }
    }
	}
}
svelte.config.js
const sveltePreprocess = require("svelte-preprocess");
module.exports = {
	preprocess: sveltePreprocess(),
};

We needed to apply a patch to the plugin (at least the version 2.7.3 - maybe there's been an update since then) as well using patch-package:

patches/eslint-plugin-svelte3+2.7.3.patch
diff --git a/node_modules/eslint-plugin-svelte3/index.js b/node_modules/eslint-plugin-svelte3/index.js
index 86ec523..cba16d2 100644
--- a/node_modules/eslint-plugin-svelte3/index.js
+++ b/node_modules/eslint-plugin-svelte3/index.js
@@ -62,6 +62,15 @@ const get_line_offsets = str => {
 	return offsets;
 };

+// find the index of the last element of an array matching a condition
+const find_last_index = (array, cond) => {

  • const idx = array.findIndex(item => !cond(item));
  • return idx === -1 ? array.length - 1 : idx - 1;
    +};

+// find the last element of an array matching a condition
+const find_last = (array, cond) => array[find_last_index(array, cond)];
+
// return a new block
const new_block = () => ({ transformed_code: '', line_offsets: null, translations: new Map() });

@@ -100,6 +109,7 @@ Linter.prototype.verify = function(code, config, options) {
processor_options.ignore_styles = settings['svelte3/ignore-styles'];
processor_options.compiler_options = settings['svelte3/compiler-options'];
processor_options.named_blocks = settings['svelte3/named-blocks'];

  • processor_options.svelte_preprocess = settings['svelte3/preprocess'];
    // call original Linter#verify
    return verify.call(this, code, config, options);
    };
    @@ -110,10 +120,94 @@ const reset = () => {
    messages: null,
    var_names: null,
    blocks: new Map(),
  •   pre_line_offsets: null,
    
  •   post_line_offsets: null,
    
  •   mappings: null,
    
    };
    };
    reset();

+var charToInteger = {};
+var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+for (var i = 0; i < chars.length; i++) {

  • charToInteger[chars.charCodeAt(i)] = i;
    +}
    +function decode(mappings) {
  • var generatedCodeColumn = 0; // first field
  • var sourceFileIndex = 0; // second field
  • var sourceCodeLine = 0; // third field
  • var sourceCodeColumn = 0; // fourth field
  • var nameIndex = 0; // fifth field
  • var decoded = [];
  • var line = [];
  • var segment = [];
  • for (var i = 0, j = 0, shift = 0, value = 0, len = mappings.length; i < len; i++) {
  •    var c = mappings.charCodeAt(i);
    
  •    if (c === 44) { // ","
    
  •        if (segment.length)
    
  •            line.push(segment);
    
  •        segment = [];
    
  •        j = 0;
    
  •    }
    
  •    else if (c === 59) { // ";"
    
  •        if (segment.length)
    
  •            line.push(segment);
    
  •        segment = [];
    
  •        j = 0;
    
  •        decoded.push(line);
    
  •        line = [];
    
  •        generatedCodeColumn = 0;
    
  •    }
    
  •    else {
    
  •        var integer = charToInteger[c];
    
  •        if (integer === undefined) {
    
  •            throw new Error('Invalid character (' + String.fromCharCode(c) + ')');
    
  •        }
    
  •        var hasContinuationBit = integer & 32;
    
  •        integer &= 31;
    
  •        value += integer << shift;
    
  •        if (hasContinuationBit) {
    
  •            shift += 5;
    
  •        }
    
  •        else {
    
  •            var shouldNegate = value & 1;
    
  •            value >>>= 1;
    
  •            if (shouldNegate) {
    
  •                value = -value;
    
  •                if (value === 0)
    
  •                    value = -0x80000000;
    
  •            }
    
  •            if (j == 0) {
    
  •                generatedCodeColumn += value;
    
  •                segment.push(generatedCodeColumn);
    
  •            }
    
  •            else if (j === 1) {
    
  •                sourceFileIndex += value;
    
  •                segment.push(sourceFileIndex);
    
  •            }
    
  •            else if (j === 2) {
    
  •                sourceCodeLine += value;
    
  •                segment.push(sourceCodeLine);
    
  •            }
    
  •            else if (j === 3) {
    
  •                sourceCodeColumn += value;
    
  •                segment.push(sourceCodeColumn);
    
  •            }
    
  •            else if (j === 4) {
    
  •                nameIndex += value;
    
  •                segment.push(nameIndex);
    
  •            }
    
  •            j++;
    
  •            value = shift = 0; // reset
    
  •        }
    
  •    }
    
  • }
  • if (segment.length)
  •    line.push(segment);
    
  • decoded.push(line);
  • return decoded;
    +}

let default_compiler;

// find the contextual name or names described by a particular node in the AST
@@ -135,7 +229,7 @@ const find_contextual_names = (compiler, node) => {
};

// extract scripts to lint from component definition
-const preprocess = text => {
+const preprocess = (text, filename) => {
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
@@ -152,10 +246,112 @@ const preprocess = text => {
return processor_options.ignore_styles(attrs) ? match.replace(/\S/g, ' ') : match;
});
}

  • // get information about the component
    let result;
  • let processedResult;
  • let processedModule;
  • let processedInstance;
  • let processedStyle;
  • let processedMarkup;
  • let moduleExt = 'js';
  • let instanceExt = 'js';
  • let moduleEndLine;
  • let processedModuleLineOffset;
  • let instanceEndLine;
  • let processedInstanceLineOffset;
    try {
  •   result = compiler.compile(text, { generate: false, ...processor_options.compiler_options });
    
  •   // run preprocessor if present
    
  •   if (processor_options.svelte_preprocess) {
    
  •   	const result = processor_options.svelte_preprocess(text, filename);
    
  •   	if (result) {
    
  •   		state.pre_line_offsets = get_line_offsets(text);
    
  •   		processedResult = result.code;
    
  •   		state.post_line_offsets = get_line_offsets(processedResult);
    
  •   		if (result.mappings) {
    
  •   			state.mappings = decode(result.mappings);
    
  •   		}
    
  •   		if (result.module) {
    
  •   			processedModule = result.module;
    
  •   			moduleExt = result.module.ext;
    
  •   		}
    
  •   		if (result.instance) {
    
  •   			processedInstance = result.instance;
    
  •   			instanceExt = result.instance.ext;
    
  •   		}
    
  •   		processedStyle = result.style;
    
  •   		processedMarkup = result.markup;
    
  •   		processor_options.named_blocks = true;
    
  •   	}
    
  •   }
    
  •   // get information about the component
    
  •   result = compiler.compile(processedResult || text, { generate: false, ...processor_options.compiler_options });
    
  •   if (processedResult) {
    
  •   	const { html, css, instance, module } = result.ast;
    
  •   	let moduleDiff = processedModule ? processedModule.diff : 0;
    
  •   	let instanceDiff = processedInstance ? processedInstance.diff : 0;
    
  •   	let styleDiff = processedStyle ? processedStyle.diff : 0;
    
  •   	let markupDiff = processedMarkup ? processedMarkup.diff : 0;
    
  •   	let modulePreOffset = 0;
    
  •   	let modulePostOffset = 0;
    
  •   	if (module) {
    
  •   		if (module.start > html.start) {
    
  •   			modulePreOffset += markupDiff;
    
  •   		}
    
  •   		if (css && module.start > css.start) {
    
  •   			modulePreOffset += styleDiff;
    
  •   		}
    
  •   		if (instance && module.start > instance.start) {
    
  •   			modulePreOffset += instanceDiff;
    
  •   		}
    
  •   		modulePostOffset = modulePreOffset + moduleDiff;
    
  •   	}
    
  •   	let instancePreOffset = 0;
    
  •   	let instancePostOffset = 0;
    
  •   	if (instance) {
    
  •   		if (instance.start > html.start) {
    
  •   			instancePreOffset += markupDiff;
    
  •   		}
    
  •   		if (css && instance.start > css.start) {
    
  •   			instancePreOffset += styleDiff;
    
  •   		}
    
  •   		if (module && instance.start > module.start) {
    
  •   			instancePreOffset += moduleDiff;
    
  •   		}
    
  •   		instancePostOffset = instancePreOffset + instanceDiff;
    
  •   	}
    
  •   	if (module && processedModule) {
    
  •   		moduleEndLine = module.content.loc.end.line;
    
  •   		processedModuleLineOffset = processedModule.ast.loc.end.line - moduleEndLine;
    
  •   		module.content.body = processedModule.ast.body;
    
  •   		module.start += modulePreOffset;
    
  •   		module.end += modulePostOffset;
    
  •   		module.content.start += modulePreOffset;
    
  •   		module.content.end += modulePostOffset;
    
  •   	}
    
  •   	if (instance && processedInstance) {
    
  •   		instanceEndLine = instance.content.loc.end.line;
    
  •   		processedInstanceLineOffset = processedInstance.ast.loc.end.line - instanceEndLine;
    
  •   		instance.content.body = processedInstance.ast.body;
    
  •   		instance.start += instancePreOffset;
    
  •   		instance.end += instancePostOffset;
    
  •   		instance.content.start += instancePreOffset;
    
  •   		instance.content.end += instancePostOffset;
    
  •   	}
    
  •   }
    

    } catch ({ name, message, start, end }) {
    // convert the error to a linting message, store it, and return
    state.messages = [
    @@ -176,27 +372,40 @@ const preprocess = text => {
    state.var_names = new Set(vars.map(v => v.name));

    // convert warnings to linting messages

  • state.messages = (processor_options.ignore_warnings ? warnings.filter(warning => !processor_options.ignore_warnings(warning)) : warnings).map(({ code, message, start, end }) => ({
  •   ruleId: code,
    
  •   severity: 1,
    
  •   message,
    
  •   line: start && start.line,
    
  •   column: start && start.column + 1,
    
  •   endLine: end && end.line,
    
  •   endColumn: end && end.column + 1,
    
  • }));
  • state.messages = (processor_options.ignore_warnings ? warnings.filter(warning => !processor_options.ignore_warnings(warning)) : warnings).map(({ code, message, start, end }) => {

  •   let fixLine = 0;
    
  •   if (processedInstanceLineOffset && start && start.line > instanceEndLine ) {
    
  •   	fixLine += processedInstanceLineOffset;
    
  •   }
    
  •   if (processedModuleLineOffset && start && start.line > moduleEndLine ) {
    
  •   	fixLine += processedModuleLineOffset;
    
  •   }
    
  •   return {
    
  •   	ruleId: code,
    
  •   	severity: 1,
    
  •   	message,
    
  •   	line: start && start.line + fixLine,
    
  •   	column: start && start.column + 1,
    
  •   	endLine: end && end.line + fixLine,
    
  •   	endColumn: end && end.column + 1,
    
  •   }
    
  • });

    // build strings that we can send along to ESLint to get the remaining messages

    if (ast.module) {
    // block for <script context='module'>
    const block = new_block();

  •   state.blocks.set('module.js', block);
    
  •   state.blocks.set(`module.${moduleExt}`, block);
    
      get_translation(text, block, ast.module.content);
    
      if (ast.instance) {
    
  •   	block.transformed_code += text.slice(ast.instance.content.start, ast.instance.content.end);
    
  •   	block.transformed_code += processedInstance
    
  •   	? processedInstance.original
    
  •   	: text.slice(ast.instance.content.start, ast.instance.content.end);
      }
    
      block.transformed_code += references_and_reassignments;
    

@@ -205,7 +414,7 @@ const preprocess = text => {
if (ast.instance) {
// block for <script context='instance'>
const block = new_block();

  •   state.blocks.set('instance.js', block);
    
  •   state.blocks.set(`instance.${instanceExt}`, block);
    
      block.transformed_code = vars.filter(v => v.injected || v.module).map(v => `let ${v.name};`).join('');
    

@@ -223,11 +432,13 @@ const preprocess = text => {

	const nodes_with_contextual_scope = new WeakSet();
	let in_quoted_attribute = false;
  •   const htmlText = processedResult || text;
    
  •   compiler.walk(ast.html, {
      	enter(node, parent, prop) {
      		if (prop === 'expression') {
      			return this.skip();
    
  •   		} else if (prop === 'attributes' && '\'"'.includes(text[node.end - 1])) {
    
  •   		} else if (prop === 'attributes' && '\'"'.includes(htmlText[node.end - 1])) {
      			in_quoted_attribute = true;
      		}
      		contextual_names.length = 0;
    

@@ -248,7 +459,7 @@ const preprocess = text => {
if (node.expression && typeof node.expression === 'object') {
// add the expression in question to the constructed string
block.transformed_code += '(';

  •   			get_translation(text, block, node.expression, { template: true, in_quoted_attribute });
    
  •   			get_translation(htmlText, block, node.expression, { template: true, in_quoted_attribute });
      			block.transformed_code += ');';
      		}
      	},
    

@@ -268,6 +479,31 @@ const preprocess = text => {
return [...state.blocks].map(([filename, { transformed_code: text }]) => processor_options.named_blocks ? { text, filename } : text);
};

+const unmap = message => {

  • for (let j = 0; j < 2; j++) {
  •   if (message[j ? 'endLine' : 'line']) {
    
  •   	const mapping = find_last(state.mappings[message[j ? 'endLine' : 'line'] - 1], ([column]) => column < message[j ? 'endColumn' : 'column']);
    
  •   	if (!mapping || mapping[1] !== 0) {
    
  •   		return false;
    
  •   	}
    
  •   	message[j ? 'endLine' : 'line'] = mapping[2] + 1;
    
  •   	message[j ? 'endColumn' : 'column'] += mapping[3] - mapping[0];
    
  •   }
    
  • }
  • if (message.fix) {
  •   for (let j = 0; j < 2; j++) {
    
  •   	const line = find_last_index(state.post_line_offsets, offset => offset < message.fix.range[j]);
    
  •   	const line_offset = state.post_line_offsets[line];
    
  •   	const mapping = find_last(state.mappings[line], ([column]) => column < message.fix.range[j] - line_offset);
    
  •   	if (!mapping || mapping[1] !== 0) {
    
  •   		return false;
    
  •   	}
    
  •   	message.fix.range[j] += mapping[3] - mapping[0] + state.pre_line_offsets[mapping[2]] - line_offset;
    
  •   }
    
  • }
  • return true;
    +};

// 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
@@ -385,6 +621,9 @@ const postprocess = blocks_messages => {
}
}
}

  • if (state.mappings) {

  •   state.messages = state.messages.filter(unmap);
    
  • }

    // sort messages and return
    const sorted_messages = state.messages.sort((a, b) => a.line - b.line || a.column - b.column);

My appologies if it doesn't work for you - it's been a while since I've coded in that codebase - stuff might be outdated

@ps73
Copy link

ps73 commented Nov 24, 2020

@IgnusG Is it possible that you create a gist for your patch file?

@IgnusG
Copy link

IgnusG commented Nov 24, 2020

@ps73 Here you go https://gist.github.com/IgnusG/8d0b6271a294a263b4185a959d8b77e0

Again, please take note this is a totally unofficial patch and it might break things/stop working at any point.
I've had success with it in our code base but your mileage may vary

All credit goes to @NicoCevallos

@niftykins
Copy link

@IgnusG I'm not having much luck getting this to actually check svelte files unless I include parserOptions.createDefaultProgram: true and remove the parserOptions.project option which is undesirable as it means I'm unable to use all of the rules which require type checking and it appears you didn't need to do that based on your eslint config.

Would you mind also posting your tsconfig.json in case there's something in there that proves helpful? 🤞

@stefanpl
Copy link

An actual deal-breaker for our team. Not being able to use TS + Eslint + Prettier without experimental patches is a clear no-no – as much as I enjoyed using svelte feature-wise. Subscribed, hoping very much for a hero to implement this.

@alexfoxy
Copy link

I'd love to see this fixed. I really want to use svelte in my next project but the lack of eslint support with typescript is holding me back!

@gustavopch
Copy link

@alexfoxy You'll find information on how to make it work in #62 comments.

TL;DR: Start with https://github.com/NicoCevallos/svelte-template and apply the code in https://gist.github.com/gustavopch/134513fa7c1f30050e968b5570c26994.

@alexfoxy
Copy link

@gustavopch thanks for the tip

@asakalou-exadel
Copy link

Hello Team, any updates regarding this fix?

I see that 3.0 has been published but still seeing errors from eslint.

Thanks!

@Drevoed
Copy link

Drevoed commented Feb 3, 2021

Any news on when this plugin will work with typescript without custom patches?

@SwiftWinds
Copy link

I applied the custom patches but now, eslint takes absolutely forever to format anything: https://www.loom.com/share/651ae074b3774cc2be14fc16cf28da0e. Anyone else have this issue? Here's the repo I'm trying to format: https://github.com/swiftwinds/recommeddit-frontend

@SwiftWinds
Copy link

EDIT: after applying the mentioned gist: https://gist.github.com/gustavopch/134513fa7c1f30050e968b5570c26994, it's a little less unbearable: https://www.loom.com/share/17b37bf96fbd4e22bc422b023f400635.

Still, eslint formatting takes about 5 seconds, which is really slow.

@gustavopch
Copy link

gustavopch commented Feb 6, 2021

@SwiftWinds Are you using type-aware rules? I don't know why, but they are slow with eslint-plugin-svelte3. Change your ESLint config to something like:

{
  files: ['**/*.ts?(x)'],
  // This will include Svelte files, so don't use type-aware rules here
},
{
  files: ['**/!(*.svelte)/*.ts'],
  // This will exclude Svelte files, so you can use type-aware rules here
},

Read this for more info on why the first glob includes Svelte files even though they use .svelte extension.

dummdidumm pushed a commit to dummdidumm/eslint-plugin-svelte3 that referenced this issue Feb 9, 2021
Closes sveltejs#68

This does not introduce a generic preprocessor-option. Instead it provides a TypeScript-specific implementation. The advantage is that we don't need hacks like deasync because transpilation and mapping can happen synchronously. It also makes post-processing and interaction with ESLint easier.

How it works:
1. transpile script contents from TS to JS
2. compile result to get Svelte compiler warnings
3. map those warnings back to its original positions
4. blank script contents
5. compile again to get the AST with original positions in the markdown part
6. use AST of step 5, vars of step 2 and blanked script content to produce the text which is handed to ESLint
7. Let the ESLint TypeScript plugin handle the TS code
8. adjust mappings
shivjm added a commit to aviralworld/frontend that referenced this issue Aug 10, 2021
This won’t work correctly until
<sveltejs/eslint-plugin-svelte3#68> is
resolved.
shivjm added a commit to aviralworld/frontend that referenced this issue Aug 10, 2021
This won’t work correctly until
<sveltejs/eslint-plugin-svelte3#68> is
resolved.
shivjm added a commit to aviralworld/frontend that referenced this issue Nov 14, 2021
This won’t work correctly until
<sveltejs/eslint-plugin-svelte3#68> is
resolved.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.