Tslint: Suporte a linting vue / arquivo html

Criado em 22 jan. 2017  ·  35Comentários  ·  Fonte: palantir/tslint

Solicitação de recurso

  • __TSLint version__: 4.3.1
  • __TypeScript version__: 2.1.5
  • __Executando TSLint via__: API Node.js

Código TypeScript sendo vinculado

<template>
  <q-layout>
    <div slot="header" class="toolbar">
      <q-toolbar-title :padding="0">
        Quasar Framework v{{quasarVersion}}
      </q-toolbar-title>
    </div>

    <!--
      Replace following "div" with
      "<router-view class="layout-view">" component
      if using subRoutes
    -->
    <div class="layout-view">
      <div class="logo-container non-selectable no-pointer-events">
        <div class="logo" :style="position">
          <img src="~assets/quasar-logo.png">
          <p class="caption text-center">
            <span class="desktop-only">Move your mouse!!!.</span>
            <span class="touch-only">Touch screen and move.</span>
          </p>
        </div>
      </div>
    </div>
  </q-layout>
</template>

<script lang="ts">
  import * as Quasar from 'quasar';
  import { Utils } from 'quasar';
  import * as Vue from 'vue';
  import Component from 'vue-class-component';

  const moveForce = 30;
  const rotateForce = 40;

  @Component({
  })
  export default class Index extends Vue {
    rotateX: number;
    rotateY: number;
    moveY: number;
    moveX: number;
    quasarVersion: string;
   ...  
 }
</script>

<style lang="stylus">
....
</style>

com configuração tslint.json :

{
  "rules": {
    "class-name": true,
    "curly": true,
    "eofline": false,
    "expr" : true,
    "forin": true,
    "indent": [true, "spaces"],
    "label-position": true,
    "label-undefined": true,
    "max-line-length": [true, 140],
    "no-arg": true,
    "no-bitwise": true,
    "no-console": [true,
      "debug",
      "info",
      "time",
      "timeEnd",
      "trace"
    ],
    "no-construct": true,
    "no-debugger": true,
    "no-duplicate-key": true,
    "no-duplicate-variable": true,
    "no-empty": true,
    "no-eval": true,
    "no-string-literal": false,
    "no-switch-case-fall-through": true,
    "no-trailing-comma": true,
    "no-trailing-whitespace": true,
    "no-unused-expression": false,
    "no-unused-variable": true,
    "no-unreachable": true,
    "no-use-before-declare": true,
    "one-line": [true,
      "check-open-brace",
      "check-catch",
      "check-else",
      "check-whitespace"
    ],
    "quotemark": [true, "single"],
    "radix": false,
    "semicolon": [false],
    "triple-equals": [true, "allow-null-check"],
    "variable-name": false,
    "whitespace": [true,
      "check-branch",
      "check-decl",
      "check-operator",
      "check-separator",
      "check-type"
    ]
  }
}

Comportamento real

Tenta lintar todo o arquivo e falha.

Comportamento esperado

verifique o código apenas dentro das tags de script, semelhante ao eslint.

Aged Away Feature Request

Comentários muito úteis

Mais algumas novidades aqui? 🤙

Todos 35 comentários

@ nrip-monotype, você pode usar o TSLint com componentes de arquivo único Vue configurando vue-loader . Por exemplo, no webpack 2 estou usando assim ( dê uma olhada na opção loaders de vue-loader ):

module: {
        rules: [
            {
                enforce: 'pre',
                test: /\.ts$/,
                loader: 'tslint-loader',
                exclude: /(node_modules)/,
                options: {
                    configFile: 'tslint.json'
                }
            },
            {
                test: /\.ts$/,
                exclude: /node_modules|vue\/src/,
                loader: 'ts-loader',
                options: {
                    appendTsSuffixTo: [/\.vue$/],
                    transpileOnly: true,
                    isolatedModules: true
                }
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        ts: 'ts-loader!tslint-loader'
                    }
                }
            },
        }
    }
}

@romandragan , sua sugestão funciona, mas parece ter problemas com no-consecutive-blank-lines . Parece que os elementos de marcação foram substituídos por linhas vazias, por exemplo:

<template>
   <span class='hello'>hello world</span>
</tempalte>
<script lang="ts">
    return {};
</script>
<style>
    .hello { background-color: pink }
</style>

É visto por tslint como:

    return {};




Se eu definir "no-consecutive-blank-lines": [true, 3] ele falha, mas "no-consecutive-blank-lines": [true, 4] é bem-sucedido ... Alguma idéia de como contornar isso? (menor que outro plug-in que remove os espaços em branco à esquerda e à direita ...)

@lucastheisen , o mesmo problema para mim 😞 Tentando encontrar uma solução ...

A configuração de @romandragan funcionou para mim, mas algo a se notar é que o sinalizador typeCheck para tslint-loader não funciona no vue-loader. Você ainda pode usá-lo normalmente fora do vue-loader.

>

module: {
        rules: [
            {
                enforce: 'pre',
                test: /\.ts$/,
                loader: 'tslint-loader',
                exclude: /(node_modules)/,
                options: {
                    configFile: 'tslint.json'
                }
            },
            {
                test: /\.ts$/,
                exclude: /node_modules|vue\/src/,
                loader: 'ts-loader',
                options: {
                    appendTsSuffixTo: [/\.vue$/],
                    transpileOnly: true,
                    isolatedModules: true,
                    typeCheck: true // This is ok.
                }
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        ts: 'ts-loader!tslint-loader' // Can't append `?typeCheck` here.
                    }
                }
            },
        }
    }
}

Tentar usar regras de verificação de tipo no vue-loader resulta em um erro como este:

ERROR in ./app.ts
(10,29): error TS2307: Cannot find module './components/sidebar.vue'.

ERROR in ./~/ts-loader!./~/tslint-loader?formatter=verbose&typeCheck!./~/vue-loader/lib/selector.js?type=script&index=0!./components/sidebar.vue
Module build failed: Error:
Invalid source file: /absolute/path/to/sidebar.vue. Ensure that the files supplied to lint have a .ts, .tsx, .js or .jsx extension.

Também estou recebendo o mesmo no-consecutive-blank-lines falso positivo que @lucastheisen e @romandragan.

Estou recebendo este ERROR in Entry module not found: Error: Can't resolve 'ts-loader!tslint-loader' ao usar esta configuração:

            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        ts: 'ts-loader!tslint-loader'
                    }
                }
            },

@ARomancev , qual versão do webpack você está usando? Você tem módulos ts-loader e tslint-loader npm instalados?

@romandragan , aqui está a configuração do npm usando:
`` `
"tslint": "^ 5.1.0",
"ts-loader": "^ 2.0.3",
"webpack": "^ 2.4.1",

And this is the webpack config:
  {
    test: /\.tsx?$/,
    enforce: 'pre',
    loader: 'tslint-loader'
  },
  {
    test: /\.tsx?$/,
    loader: 'ts-loader',
    exclude: /node_modules/,
    options: {
      appendTsSuffixTo: [/\.vue$/]
    }
  },

`` `
ts-loader e tslint-loader instalados e funcionam bem desde que recebo o lint correto dos arquivos * .ts.

Como solução alternativa, podemos separar a lógica TypeScript do arquivo .vue e remover tslint-loader dos carregadores vue. Então, no-consecutive-blank-lines desaparece.

@romandragan isso funciona, mas seria bom <script> também: isso é necessário para suporte do editor e é muito mais fácil executar o comando tslint separadamente, ao invés de através do webpack inteiro fluxo.

@adidahiya algum plano para esse recurso?
ou algum plano de suporte ao sistema de plug-ins em tslint, como plug-ins eslint?

Se você estiver usando o Webpack, eu tenho .vue arquivos funcionando e linting no nível do typechecker sem nenhum problema de no-consecutive-blank-lines no fork-ts-checker-webpack-plugin . Você pode ver o PR aqui (e npm install de um branch de teste e usá-lo agora, consulte o topo do tópico de PR): https://github.com/Realytics/fork-ts-checker-webpack-plugin / pull / 77

Além disso, se você estiver usando o editor VSCode, verifique a extensão TSLint Vue .

Eu criei uma solicitação pull que implementa um recurso de plug-in em tslint e escrevi o primeiro plug-in capaz de analisar componentes de arquivo único "vue".

https://github.com/palantir/tslint/pull/3596
https://github.com/Toilal/tslint-plugin-vue

Este é um trabalho em andamento, mas sinta-se à vontade para tentar. Você pode adicionar o plugin com npm install git+https://https://github.com/Toilal/tslint-plugin-vue e habilitá-lo adicionando plugins: 'vue' em tslint.json . Atualmente ele não funciona com a opção -p/--project , você deve usar a opção -c/--config .

Olá pessoal, outra solução alternativa, por enquanto, é mover a tag do script no início do arquivo e adicionar o /* tslint:disable:no-consecutive-blank-lines */ na última linha para não levar em conta essa regra.
Confira a imagem abaixo
image

O Vue-loader pode realmente extrair JavaScript ou TypeScript de arquivos vue, portanto, a análise de arquivos vue não é um problema para o webpack. No entanto, o TSLint ainda gera "Arquivo de origem inválido" porque os nomes dos arquivos terminam com ".vue" se typeCheck estiver habilitado ...

Além disso, podemos fazer o TSLint parar de reclamar de linhas em branco consecutivas, permitindo linhas em branco consecutivas no início ou no final dos arquivos vue, porque o vue-loader não exclui linhas irrelevantes para o TypeScript, mas as apaga para manter os números de linha corretos.

Atualmente estou trabalhando em um linter que poderia resolver esses problemas sem a necessidade de webpack: https://github.com/ajafff/wotan
Atualmente, esta é uma prova de conceito e pode ou não ser integrada ao TSLint. É uma reescrita completa do zero e praticamente incompatível com o TSLint.

Ele tem a capacidade de transformar arquivos usando um processador (semelhante aos processadores ESLint). Um processador vue extrai o código TypeScript do SFC, o linter apenas lança o código e, em seguida, o processador mapeia os erros para o local correto no arquivo original. Isso funciona até mesmo com verificação de tipo.
Você pode ver um exemplo de saída de linting um arquivo vue aqui:
https://github.com/ajafff/wotan/blob/master/baselines/integration/processors/vue/default/hello.vue.lint#L29

Também permite a fixação automática. O mesmo arquivo acima foi corrigido automaticamente: https://github.com/ajafff/wotan/blob/master/baselines/integration/processors/vue/default/hello.vue#L28

Depois de corrigir https://github.com/ajafff/wotan/issues/32 , publicarei uma versão para que você possa experimentá-la em seu código do mundo real.
Observe que o processador vue não faz parte do projeto principal, mas certificarei de publicar um pacote separado para o processador.

Alguém sabe como eu configuraria tsconfig.json para que o tslint da linha de comando lint a parte TS dos meus arquivos Vue? Funciona bem no VS Code, mas gostaria que a linha de comando funcionasse também.

Demorei um pouco mais do que pensava, mas aqui está: https://www.npmjs.com/package/@fimbul/wotan

Você pode até usar o tempo de execução do linter ( @fimbul/wotan ) para executar as regras do TSLint. Você só precisa de @fimbul/heimdall , consulte https://github.com/fimbullinter/wotan/tree/master/packages/heimdall#readme

Para lintar arquivos Vue, use @fimbul/ve (sem erro de digitação, não há 'u' em 've'): https://github.com/fimbullinter/wotan/tree/master/packages/ve#readme

Há uma programação para quando o tslint oferecerá suporte a arquivos vue / html linting? @Toilal

Cabe à comunidade implementar isso, mas o autor do VueJS parece favorecer os plug-ins ESLint TypeScript na última versão do vue-cli (atualmente em alfa).

Este recurso parece já estar implementado em [email protected] . Corre:

$ npm install -g @vue/cli
$ vue create project-name

E haverá a opção de usar o TSLint como o linter.

Estou de volta com notícias ainda melhores para todos neste tópico:

A última versão do wotan pode executar regras TSLint de acordo com seu tslint.json e adiciona suporte para processadores. Isso significa que você não precisa mudar sua configuração e pode começar a criar seus arquivos Vue agora:

  1. Instalar
    sh yarn add -D @fimbul/wotan @fimbul/ve @fimbul/valtyr # or npm install --save-dev @fimbul/wotan @fimbul/ve @fimbul/valtyr
  2. Configurar
    Adicione um novo arquivo .fimbullinter.yaml no diretório raiz do seu projeto e adicione o seguinte conteúdo:
    yaml modules: "@fimbul/valtyr" valtyr: overrides: - files: "*.vue" processor: "@fimbul/ve"
  3. Corre
    Veja os exemplos abaixo e adapte para seu próprio uso. Leia os documentos para obter mais informações sobre os argumentos CLI disponíveis.
    sh wotan # finds tsconfig.json and lints the whole project with type information according to your tslint.json wotan 'src/**/*.vue' -f verbose # lint all Vue files, use TSLint's verbose formatter wotan -p tsconfig.json -c tslint.json --fix # lint the whole project with tslint.json and fix failures
  4. Leitura Adicional
    Wotan - CLI e configuração: https://github.com/fimbullinter/wotan/tree/master/packages/wotan#readme
    Valtýr - plugin para regras e formatadores TSLint - "o tempo de execução do TSLint que é melhor que o TSLint": https://github.com/fimbullinter/wotan/tree/master/packages/valtyr#readme
    Vé - processador para componentes de arquivo único Vue: https://github.com/fimbullinter/wotan/tree/master/packages/ve#readme
    Fimbullinter - por que você deve começar a usar este projeto agora: https://github.com/fimbullinter/wotan#readme
  5. Curta, compartilhe e assine: estrela:

@romandragan

você pode usar o TSLint com componentes de arquivo único Vue configurando o vue-loader.

Obrigado pela solução. Mas é apenas uma solução específica do Webpack. Seria ótimo se houvesse uma solução genérica que não dependa de uma ferramenta de construção para que pudéssemos usar tslint em arquivos Vue compilados com o Fusebox (ou qualquer outra ferramenta de construção).

Outra solução para webpack.

Eu criei um carregador simples que apara todos os espaços em branco de um "arquivo" fornecido pelo vue-loader e, em seguida, adiciona um espaço em branco para um linter.

webpack.config.js:

test:/\.vue$/, loader: 'vue-loader', options: { loaders: { 'ts': [ 'vue-ts-loader', 'tslint-loader', path.resolve('./path/to/remove-whitespace-ts-loader.js') ],....

e, em seguida, remove-whitespace-ts-loader:
/* MIT License http://www.opensource.org/licenses/mit-license.php Author Szymon Sasin */ module.exports = function(source) { let result = source.replace(/^\s+|\s+$/g, '') result += '\r\n' return result; }
_Qualquer ajuda sobre como melhorar a formatação do código bem-vinda_

Funciona bem e não permite modificar as fontes, obrigado

Assim, estou na mesma página, isso não será corrigido a menos que seja feito como um PR?

Além de no-consecutive-blank-lines não funcionar nesta configuração (que deve ser contornável com um carregador personalizado), estou apenas observando que, mesmo com versões recentes de webpack e vue-loader, não consigo obter o typeCheck: true trabalhando para *.vue arquivos porque tslint está descontente com a extensão (mesmo com appendTsSuffixTo ). Este projeto de demonstração fornece um exemplo simples para brincar.

marca

Mais algumas novidades aqui? 🤙

Se alguém quiser usar o cli para lintar seu arquivo .vue, você pode tentar o vue-tslint . Não é perfeito, mas funciona ...

Observe que a solução de @romandragan agora não é a melhor prática (não tenho certeza se era antes). Em vez disso, adicione tslint-loader às suas regras de use em \.ts$ como você faria para arquivos de texto datilografado usuais; agora é vue-loader lida com arquivos de modelo em geral, delegando as diferentes seções à configuração do Webpack para essas respectivas extensões. O componente de plug-in de vue-loader extrairá as regras para \.ts$ e transmitirá <script lang="ts"> blocos por meio dessas regras.

Para aqueles que usam Vue CLI, adicione um

config.module.rule('ts')
  .use('tslint-loader')
  .loader('tslint-loader');

declaração para sua opção chainWebpack em seu vue.config.js . Por exemplo,

vue.config.js

module.exports = {
  chainWebpack: (config) => {
    config.devtool('source-map');
    config.module.rule('ts')
      .use('tslint-loader')
      .loader('tslint-loader');
  },
  pluginOptions: {
    apollo: {
      enableMocks: true,
      enableEngine: true
    }
  }
}

Isso funcionou para mim

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')

module.exports = (baseConfig, env, defaultConfig) => {
  defaultConfig.resolve.extensions.push('.ts', '.tsx', '.vue', '.css', '.less', '.scss', '.sass', '.html')

  defaultConfig.module.rules.push( {
    test: /\.ts$/,
    exclude: /(node_modules)/,
    use: [
      {
        loader: 'ts-loader',
        options: {
          appendTsSuffixTo: [/\.vue$/]
          // transpileOnly: true,
        }
      },
      {
        loader: 'tslint-loader',
        options: {
          configFile: 'tslint.json',
          emitErrors: true,
        }
      }
    ]
  })

  defaultConfig.module.rules.push({ test: /\.less$/, loaders: [ 'style-loader', 'css-loader', 'less-loader' ] })
  defaultConfig.module.rules.push({ test: /\.scss$/, loaders: [ 'style-loader', 'css-loader', 'sass-loader' ] })
  defaultConfig.module.rules.push({ test: /\.styl$/, loader: 'style-loader!css-loader!stylus-loader' })

  defaultConfig.plugins.push(new ForkTsCheckerWebpackPlugin())

  return defaultConfig
}

De acordo com o nº 4379, uma solução alternativa específica do Vue não será capaz de pousar no núcleo do TSLint:

Dada a falta de discussão ou proposta concreta aqui e a iminente depreciação do TSLint em favor do ESLint (# 4534), vou prosseguir e encerrar este problema e relatórios específicos do Vue relacionados para fins de manutenção.

Se isso ainda for um problema para você no typescript-eslint , eu recomendo preencher um problema lá. Boa sorte!

./node_modules/.bin/wotan 'src / * / .vue' -f detalhado

Falhas com:

Error: ENOENT: no such file or directory, open '/home/andrew/PycharmProjects/djangochat/fe/src/components/App.vue.ts'
    at Object.openSync (fs.js:451:3)
    at detectEncoding (/home/andrew/PycharmProjects/djangochat/fe/node_modules/tslint/lib/rules/encodingRule.js:67:17)
    at walk (/home/andrew/PycharmProjects/djangochat/fe/node_modules/tslint/lib/rules/encodingRule.js:49:20)
    at Rule.AbstractRule.applyWithFunction (/home/andrew/PycharmProjects/djangochat/fe/node_modules/tslint/lib/language/rule/abstractRule.js:39:9)
    at Rule.apply (/home/andrew/PycharmProjects/djangochat/fe/node_modules/tslint/lib/rules/encodingRule.js:33:21)
    at R.apply (/home/andrew/PycharmProjects/djangochat/fe/node_modules/@fimbul/bifrost/src/index.js:30:40)
    at Linter.applyRules (/home/andrew/PycharmProjects/djangochat/fe/node_modules/@fimbul/wotan/src/linter.js:209:31)
    at Linter.getFindings (/home/andrew/PycharmProjects/djangochat/fe/node_modules/@fimbul/wotan/src/linter.js:125:25)
    at Runner.lintFiles (/home/andrew/PycharmProjects/djangochat/fe/node_modules/@fimbul/wotan/src/runner.js:159:43)
    at lintFiles.next (<anonymous>) {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: '/home/andrew/PycharmProjects/djangochat/fe/src/components/App.vue.ts'
}

@akoidan, por favor, traga questões como essa com o projeto wotan, não tslint

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

adidahiya picture adidahiya  ·  3Comentários

dashmug picture dashmug  ·  3Comentários

ypresto picture ypresto  ·  3Comentários

zewa666 picture zewa666  ·  3Comentários

DanielKucal picture DanielKucal  ·  3Comentários