Last active
January 4, 2022 14:08
-
-
Save pyrsmk/464f366de8dab22ac27d2d3ff860b668 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Currently, the ESLint plugin used by Svelte is buggy and choke on files with Sass. | |
// This little implementation takes care of removing styling from Svelte components as | |
// as well as handle any type of files other than Svelte, with complete respect of rules | |
// from the base ESLint plugin (that is, `.eslintrc.cjs` rules are used). It has been | |
// thought to be simple to use and integrate. | |
// | |
// https://github.com/sveltejs/eslint-plugin-svelte3/issues/10 | |
// | |
// Usage example: | |
// | |
// node svelte-lint.js 'src/**/*' | |
// | |
// We can use STDIN too! For example, we can lint only staged files: | |
// | |
// git --no-pager diff --name-only --cached | node svelte-lint.js | |
import { argv } from 'process' | |
import { ESLint } from 'eslint' | |
import { FileEnumerator } from 'eslint/lib/cli-engine/file-enumerator.js' | |
import fs from 'fs' | |
import path from 'path' | |
const lint = async (globs) => { | |
let problemsInFiles = false | |
const supportedExtensions = [ '.js', '.ts', '.svelte' ] | |
const eslint = new ESLint() | |
const fileEnumerator = new FileEnumerator() | |
// We could have pass the globs directly to `iterateFiles`, but if no files are found | |
// it throws a NoFilesFound error. So we need to keep that error silent to avoid to | |
// break the linting process. | |
await Promise.all( | |
globs.map(async glob => { | |
try { | |
// Disable some rules for Svelte files. | |
for (const { filePath } of fileEnumerator.iterateFiles(glob)) { | |
if (!supportedExtensions.includes(path.extname(filePath))) { | |
return | |
} | |
let contents = fs.readFileSync(filePath, 'utf8') | |
// The magic happens here. If it's a Svelte file we remove the style tag. | |
if (filePath.endsWith('.svelte')) { | |
contents = contents.replace(/<style.*?<\/style>/gs, '') | |
} | |
const results = await eslint.lintText(contents, { filePath }) | |
const formatter = await eslint.loadFormatter('stylish') | |
const report = formatter.format(results) | |
if (report.length > 0) { | |
problemsInFiles = true | |
console.log(report) | |
} | |
} | |
} catch (error) { | |
if (error.constructor.name == 'NoFilesFoundError') { | |
return | |
} | |
throw error | |
} | |
}) | |
) | |
// Problems have been found, let's throw an error so the process exits with a proper | |
// code. | |
if (problemsInFiles) { | |
throw new Error() | |
} | |
} | |
// Take glob arguments and merge them with paths passed via STDIN. | |
let globs = argv.slice(2) | |
try { | |
const stdin = fs.readFileSync(0) | |
globs = globs.concat( | |
stdin.toString().split('\n').filter(path => path != '') | |
) | |
} catch (e) {} | |
lint(globs).catch(error => { | |
process.exitCode = 1 | |
// When there are problems in files we throw an error with no message. Hence, we don't | |
// want to display it. | |
if (error.message) { | |
console.error(error) | |
} | |
}) |
I wasn't aware of that, thanks! I'm replacing it.
@Perturbatio Just letting you know that I added a way to parse files passed from STDIN (very useful for only parse modified/staged files, for example).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, thanks for writing this, I modified the regex to be global so that multiple style blocks can be replaced.
(since svelte files can contain multiple style blocks, e.g. styles in svelte:head vs styles for the component itself)