diff --git a/htmlhint-server/package.json b/htmlhint-server/package.json
index 95b5af7..421e1bd 100644
--- a/htmlhint-server/package.json
+++ b/htmlhint-server/package.json
@@ -1,6 +1,6 @@
{
"name": "htmlhint-server",
- "version": "0.5.0",
+ "version": "0.5.2",
"description": "HtmlHint Linter Server",
"engines": {
"node": "*"
@@ -10,7 +10,8 @@
"fs": "0.0.2",
"htmlhint": "^0.9.13",
"strip-json-comments": "^2.0.0",
- "vscode-languageserver": "^3.4.0"
+ "vscode-languageserver": "^3.4.0",
+ "glob": "5.0.15"
},
"devDependencies": {
"@types/node": "^6.0.41",
diff --git a/htmlhint-server/src/server.ts b/htmlhint-server/src/server.ts
index 3c228c9..ac47e18 100644
--- a/htmlhint-server/src/server.ts
+++ b/htmlhint-server/src/server.ts
@@ -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;
+ 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, '/');
+ if(fs.existsSync(rulesdir)){
+ if(fs.statSync(rulesdir).isDirectory()){
+ rulesdir += /\/$/.test(rulesdir)?'':'/';
+ rulesdir += '**/*.js';
+ var arrFiles = glob.sync(rulesdir, {
+ '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){}
+}
+
/**
* 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 => {
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());
});
diff --git a/htmlhint-server/src/typings-custom/htmlhint.d.ts b/htmlhint-server/src/typings-custom/htmlhint.d.ts
index 050a93e..914eb06 100644
--- a/htmlhint-server/src/typings-custom/htmlhint.d.ts
+++ b/htmlhint-server/src/typings-custom/htmlhint.d.ts
@@ -5,6 +5,7 @@ declare module 'htmlhint' {
export interface Verifier {
verify(text: string): Error[];
+ loadCustomRules(rulesdir: string): any;
}
export interface Error {
diff --git a/htmlhint/README.md b/htmlhint/README.md
index 8f6506c..5550f43 100644
--- a/htmlhint/README.md
+++ b/htmlhint/README.md
@@ -78,11 +78,12 @@ If your file type already has an associated language service other than "html",
## Settings
-The HTMLHint extension provides three [settings](https://code.visualstudio.com/docs/customization/userandworkspace):
+The HTMLHint extension provides four [settings](https://code.visualstudio.com/docs/customization/userandworkspace):
* `htmlhint.enable` - disable the HTMLHint extension globally or per workspace.
* `htmlhint.documentSelector` - specify additional language services to be linted
* `htmlhint.options` - provide a rule set to override on disk `.htmlhintrc` or HTMLHint defaults.
+* `htmlhint.rulesDir` - provide an absolute or relative path to a folder containing custom rules.
You can change settings globally (**File** > **Preferences** > **User Settings**) or per workspace (**File** > **Preferences** > **Workspace Settings**). The **Preferences** menu is under **Code** on macOS.
diff --git a/htmlhint/package.json b/htmlhint/package.json
index 7f1f7ac..f43f553 100644
--- a/htmlhint/package.json
+++ b/htmlhint/package.json
@@ -3,7 +3,7 @@
"displayName": "HTMLHint",
"description": "VS Code integration for HTMLHint - A Static Code Analysis Tool for HTML",
"icon": "HTMLHint.png",
- "version": "0.5.0",
+ "version": "0.5.2",
"publisher": "mkaufman",
"galleryBanner": {
"color": "#0000FF",
@@ -40,6 +40,11 @@
"default": true,
"description": "Control whether htmlhint is enabled for HTML files or not."
},
+ "htmlhint.rulesDir": {
+ "type": "string",
+ "default": "",
+ "description": "Folder containing custom rules, absolute or relative to workspace root."
+ },
"htmlhint.documentSelector": {
"type": "array",
"default": [