-
Notifications
You must be signed in to change notification settings - Fork 35
Add rules directory configuration #45
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,18 +10,23 @@ import * as path from 'path'; | |
| import * as server from 'vscode-languageserver'; | ||
| import htmlhint = require('htmlhint'); | ||
| import fs = require('fs'); | ||
| import glob = require('glob'); | ||
|
|
||
| let stripJsonComments: any = require('strip-json-comments'); | ||
|
|
||
| interface Settings { | ||
| htmlhint: { | ||
| enable: boolean; | ||
| options: any; | ||
| rulesDir: string; | ||
| } | ||
| [key: string]: any; | ||
| } | ||
|
|
||
| let settings: Settings = null; | ||
| let linter: any = null; | ||
| let rulesLoaded: boolean = false; | ||
| let rootFolder: string = null; | ||
|
|
||
| /** | ||
| * This variable is used to cache loaded htmlhintrc objects. It is a dictionary from path -> config object. | ||
|
|
@@ -60,6 +65,67 @@ function getRange(error: htmlhint.Error, lines: string[]): any { | |
| }; | ||
| } | ||
|
|
||
| function loadRules(): any { | ||
| rulesLoaded = false; | ||
| if (linter == null || !settings.htmlhint || !settings.htmlhint.rulesDir) { | ||
| return; | ||
| } | ||
|
|
||
| let rulesDir = settings.htmlhint.rulesDir; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you should be able to do something like Or alternatively, |
||
| let absoluteDir = ''; | ||
| //check absolute path | ||
| let exists = fs.existsSync(rulesDir); | ||
| if (exists) { | ||
| absoluteDir = rulesDir; | ||
| } else { | ||
| //relative dir, find it based on workspace roots | ||
| absoluteDir = path.resolve(rootFolder, rulesDir); | ||
| exists = fs.existsSync(absoluteDir); | ||
| } | ||
|
|
||
| if (exists) { | ||
| //load all rules | ||
| loadCustomRules(absoluteDir); | ||
| } | ||
| rulesLoaded = true; | ||
| } | ||
|
|
||
| // loadCustomRules is a direct copy from ./htmlhint-server/node_modules/htmlhint/bin/htmlhint lines 139-160 | ||
| // load custom rles | ||
| function loadCustomRules(rulesdir:string): any{ | ||
| rulesdir = rulesdir.replace(/\\/g, '/'); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A comment here would help those of us who don't have a built-in regex parser. :)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similiarly for other regexes used in here.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I copied both loadCustomRules and loadRule from the htmlhint module's source code as it is not exposed for us to use.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally instead of copy/pasting this, we'd get these methods exposed via htmlhint. This way, we don't break the VS Code exetension when htmlhint changes their implementation. Do you know what a PR would look like to refactor in htmlhint? /cc @thedaviddias. |
||
| if(fs.existsSync(rulesdir)){ | ||
| if(fs.statSync(rulesdir).isDirectory()){ | ||
| rulesdir += /\/$/.test(rulesdir)?'':'/'; | ||
| rulesdir += '**/*.js'; | ||
| var arrFiles = glob.sync(rulesdir, { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A comment here explaining what files you're going to load would be helpful as well. |
||
| 'dot': false, | ||
| 'nodir': true, | ||
| 'strict': false, | ||
| 'silent': true | ||
| }); | ||
| arrFiles.forEach(function(file){ | ||
| loadRule(file); | ||
| }); | ||
| } | ||
| else{ | ||
| loadRule(rulesdir); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // loadCustomRules is a modified copy from ./htmlhint-server/node_modules/htmlhint/bin/htmlhint lines 162-170 | ||
| // Only the variable name HTMLHint has been changed to linter | ||
| // load rule | ||
| function loadRule(filepath: string): any{ | ||
| filepath = path.resolve(filepath); | ||
| try{ | ||
| var module = require(filepath); | ||
| module(linter); | ||
| } | ||
| catch(e){} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. blanket catch seems problematic here. Is this here for a reaason?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I expect the idea is to skip a rule if it is broken. Given that this code is from htmlhint's source there might not be a way to properly report errors from there. Can you please suggest a nice way we can report errors to the user as we have access to vscode here?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think vs code APIs let you report errors with something like |
||
| } | ||
|
|
||
| /** | ||
| * Given an htmlhint.Error type return a VS Code server Diagnostic object | ||
| */ | ||
|
|
@@ -178,17 +244,16 @@ function trace(message: string, verbose?: string): void { | |
| } | ||
|
|
||
| connection.onInitialize((params: server.InitializeParams, token: server.CancellationToken) => { | ||
| let rootFolder = params.rootPath; | ||
| rootFolder = params.rootPath; | ||
| let initOptions: { | ||
| nodePath: string; | ||
| } = params.initializationOptions; | ||
| let nodePath = initOptions ? (initOptions.nodePath ? initOptions.nodePath : undefined) : undefined; | ||
|
|
||
| const result= server.Files.resolveModule2(rootFolder, 'htmlhint', nodePath, trace). | ||
| const result = server.Files.resolveModule2(rootFolder, 'htmlhint', nodePath, trace). | ||
| then((value): server.InitializeResult | server.ResponseError<server.InitializeError> => { | ||
| linter = value.HTMLHint; | ||
| //connection.window.showInformationMessage(`onInitialize() - found local htmlhint (version ! ${value.HTMLHint.version})`); | ||
|
|
||
| //connection.window.showInformationMessage(`onInitialize() using external htmlhint(version ! ${linter.version})`); | ||
| let result: server.InitializeResult = { capabilities: { textDocumentSync: documents.syncKind } }; | ||
| return result; | ||
| }, (error) => { | ||
|
|
@@ -208,11 +273,9 @@ function doValidate(connection: server.IConnection, document: server.TextDocumen | |
| let fsPath = server.Files.uriToFilePath(uri); | ||
| let contents = document.getText(); | ||
| let lines = contents.split('\n'); | ||
|
|
||
| let config = getConfiguration(fsPath); | ||
|
|
||
| let errors: htmlhint.Error[] = linter.verify(contents, config); | ||
|
|
||
| let diagnostics: server.Diagnostic[] = []; | ||
| if (errors.length > 0) { | ||
| errors.forEach(each => { | ||
|
|
@@ -239,7 +302,7 @@ documents.onDidChangeContent((event) => { | |
| // The VS Code htmlhint settings have changed. Revalidate all documents. | ||
| connection.onDidChangeConfiguration((params) => { | ||
| settings = params.settings; | ||
|
|
||
| loadRules(); | ||
|
|
||
| validateAllTextDocuments(connection, documents.all()); | ||
| }); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: looks like indentation is messed up in
loadRules()