-
Notifications
You must be signed in to change notification settings - Fork 889
In browser linting #1001
Comments
Hi, same question, is it possible at this time to do Typescript linting in the browser? |
It's not possible. TSLint uses several node.js APIs ( A better way is introducing some kind of abstraction like TypeScript's CompilerHost. That's a rather big refactoring, though. I'll take a look at eslint to see how they do it. |
For posterity: here's the discussion in the eslint repo eslint/eslint#2585 and eslint/eslint#8348 |
Was curious about what it would take to mimic the eslint demo feature and stumbled on this discussion. It looks like TSLint relies on those Node packages primarily for configuration handling, and the Linter itself does not make much use of them. Is that fair to say? I'm NOT suggesting TSLint support the browser, but how about recreating that feature for the docs? People seem to want code examples, and a TSLint Playground would address that in a big way. |
@aervin I don't think this solves our documentation issue. But it would be nice to just test rules without installing everything locally. Almost all rules don't do any IO, so they would work in the browser. But there are some parts that rely heavily on a node environment:
|
Thanks @ajafff. Looks like a simple proof of concept is in order to gather requirements for the browser. And soon I'll post a proposal for adding code examples to the rule docs. |
Update:
CompilerHostimport * as ts from "typescript";
export default function createCompilerHostForBrowser(
options: ts.CompilerOptions,
moduleSearchLocations: string[],
): ts.CompilerHost {
return {
getSourceFile,
getDefaultLibFileName: () => "lib.d.ts",
writeFile: (fileName, content) =>
localStorage.setItem("source", content),
getCurrentDirectory: () => "/",
getDirectories: path => ["/"],
getCanonicalFileName: fileName => "TSLintPlaygroundFile.ts",
getNewLine: () => "\n",
useCaseSensitiveFileNames: function() {
return false;
},
fileExists,
readFile,
resolveModuleNames,
};
function fileExists(fileName: string): boolean {
return localStorage.getItem("source") !== undefined;
}
function readFile(fileName: string): string | undefined {
return localStorage.getItem("source");
}
function getSourceFile(
fileName: string,
languageVersion: ts.ScriptTarget,
onError?: (message: string) => void,
) {
const sourceText = localStorage.getItem("source");
return sourceText !== undefined
? ts.createSourceFile(
this.getCanonicalFileName(),
sourceText,
languageVersion,
)
: undefined;
}
function resolveModuleNames(
moduleNames: string[],
containingFile: string,
): ts.ResolvedModule[] {
return [
{
resolvedFileName: "./mod.js", /* I'm not sure what's up with this */
},
];
}
} Webpack/* webpack.config.js */
module.exports = {
entry: "./src/app.ts",
output: {
filename: "bundle.js",
path: __dirname,
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: "ts-loader",
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
node: {
os: "empty",
fs: "empty",
glob: "empty"
},
}; Significant changes to TSLintThe public static createProgram(): ts.Program {
const options: ts.CompilerOptions = {
module: ts.ModuleKind.AMD,
target: ts.ScriptTarget.ES5,
};
const sourceFiles = [localStorage.getItem("source")];
const host = createCompilerHostForBrowser(options, ["./"]);
return ts.createProgram(sourceFiles, options, host);
} I loaded the rule this way, which I know is not ideal import { Rule } from "./rules/noConsoleRule"; /* not exported from tslint; copied to repo and exported */
export default class Linter {
public static VERSION = "5.8.0";
/* ... */
private getEnabledRules(
configuration: IConfigurationFile = DEFAULT_CONFIG,
isJs: boolean,
): IRule[] {
/* Oh no! The ruleLoader function uses Node APIs. What can be done? */
return [
new Rule({
ruleArguments: [],
ruleName: "no-console",
ruleSeverity: "error",
disabledIntervals: [],
}),
];
}
/* ... */
} Questions
|
For those interested, astexplorer.net has already come up with a promising browser implementation. Perhaps we can piggy-back off some of their work to bring the TSLint core rules to the browser. |
Hey everyone. I've built a thing that does this, and currently just waiting to get the repo transferred over to the Palantir organization before making the URL public. I'll update this issue, as well as the main README and other docs when that happens (hopefully soon). |
Announcing the |
Hi there,
I was wondering if it is technically possible to do Typescript linting in the browser... well, everything is possible, but is it a huge undertaking? Projects like
eslint
andcoffee-lint
does this. The benefit is allowing in browser code editors to have linting. I am working on one of those services, http://webpackbin.herokuapp.com, but there is of course lots of other services that could benefit from this. Like JSBin, cloud9, nitrous etc.So yeah, kind of an open question. Thanks!
The text was updated successfully, but these errors were encountered: