Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Add rules directory configuration #45

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

dtminnaar
Copy link

We use custom html hinting rules, this is a small improvement to allow you to specify the folder containing those rules.

@msftclas
Copy link

msftclas commented Sep 26, 2018

CLA assistant check
All CLA requirements met.

@aleh-vasilyeu
Copy link

aleh-vasilyeu commented Sep 28, 2018

@ganralf great job!
@mike-kaufman I look forward to this feature :D

@rene-leanix
Copy link

@mike-kaufman, would be great if this could be merged some time soon to add support for custom rules.

1 similar comment
@rene-leanix
Copy link

@mike-kaufman, would be great if this could be merged some time soon to add support for custom rules.

Copy link
Contributor

@mike-kaufman mike-kaufman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ganralf! I added some questions. Forgive me if any are obvious, as I don't look at this code too frequently. :)

rulesLoaded = false;
}

if (rulesLoaded || htmlhint == null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is htmlhint here? The param is HTMLHint.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, that check is pointless

loadCustomRules(absoluteDir, HTMLHint);
}
}
catch (e) { }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are exceptions getting swallowed here? Is this necessary?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loadCustomRules does error handling, I will remove the try/catch in this method


// load custom rles
function loadCustomRules(rulesdir:string, HTMLHint:any):any{
rulesdir = rulesdir.replace(/\\/g, '/');
Copy link
Contributor

Choose a reason for hiding this comment

The 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. :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similiarly for other regexes used in here.

Copy link
Author

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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.statSync(rulesdir).isDirectory()){
rulesdir += /\/$/.test(rulesdir)?'':'/';
rulesdir += '**/*.js';
var arrFiles = glob.sync(rulesdir, {
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

'silent': true
});
arrFiles.forEach(function(file){
loadRule(file, HTMLHint);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the motivation for letting someone specify a directory here? It seems like doing that will result in the extension require-ing every JS file in the directory, which could easily be problematic.

Can you support a single file, or an explicit list of files?
What does basic htmlhint allow here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way the plugin works (as I understand it) is you can create multiple rules in as many files and subfolders as you wish.
Each .js file in the rules folder will be loaded into memory.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought they had to be specified in the rules list as well via htmlhintrc or --rules on the command line.

var module = require(filepath);
module(HTMLHint);
}
catch(e){}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blanket catch seems problematic here. Is this here for a reaason?

Copy link
Author

Choose a reason for hiding this comment

The 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?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think vs code APIs let you report errors with something like connection.window.showErrorMessage(...message...); See API docs [here](https://code.visualstudio.com/docs/extensionAPI/vscode-api_

@@ -60,6 +65,74 @@ function getRange(error: htmlhint.Error, lines: string[]): any {
};
}

function loadRules(HTMLHint: any, force: boolean): any {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for consitency, I'd call HTMLHint linter or htmlHintLinter - something to indicate that it is an instance ofa linter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or can you just use the module var linter here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that will be better, will make that change

@mike-kaufman
Copy link
Contributor

Please @-mention me if I go dark on this. :)

Copy link
Contributor

@mike-kaufman mike-kaufman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some more comments... getting closer :)

rulesLoaded = false;
if (linter == null || !settings.htmlhint || !settings.htmlhint.rulesDir) {
return;
}
Copy link
Contributor

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()

return;
}

let rulesDir = settings.htmlhint.rulesDir;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should be able to do something like const rulesDir = path.resolve(settings.htmlhint.rulesDir);, and then drop all the stuff from lines 75-84?

Or alternatively, const rulesDir = path.resolve(rootDir, settings.htmlhint.rulesDir);


// load custom rles
function loadCustomRules(rulesdir:string, HTMLHint:any):any{
rulesdir = rulesdir.replace(/\\/g, '/');
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

var module = require(filepath);
module(HTMLHint);
}
catch(e){}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think vs code APIs let you report errors with something like connection.window.showErrorMessage(...message...); See API docs [here](https://code.visualstudio.com/docs/extensionAPI/vscode-api_

@miramardesign
Copy link

so is there any way to load a /rules directory in .htmlhintrc? is that a different issue?

@davehibshman
Copy link

@miramardesign I haven't looked at the HTMLHint source, but the documentation suggests custom rules go in a sub-folder and you use the --rulesdir on the command line to pic them up. To turn them on you can either include the custom rule name in your rc file or you can include it on the command line using the --rules option.

@carlkenne
Copy link

Nice job here guys. What's the status on this one?

@konstantintieber
Copy link

konstantintieber commented Oct 7, 2019

Do you need help here? This feature would help us tremendously in developing our Angular frontend, by helping users piece together components, that rely on specific contentChildren to work.
For example you have a <dropdown> component, that only works as long as it has <option> children.

Such a linter is little help, when it's only evaluated when executing the npm command, but very helpful, when the IDE evaluates it automatically.

A linter could look like this:

module.exports = (HTMLHint) => {
  HTMLHint.addRule({
    id: 'dropdown',
    description: 'Cannot use dropdown without providing option children',
    init: function (parser, reporter) {
      var self = this;
      var listeningToTagsInDropdown = false;
      var hasOptionChildren = false;
      parser.addListener('tagstart', function(event) {
        var tagName = event.tagName.toLowerCase();
        if (tagName === 'dropdown') {
          listeningToTagsInDropdown = true;
        } else if (tagName === 'option' && listeningToTagsInDropdown) {
            hasOptionChildren = true;
        }
      });
      parser.addListener('tagend', function(event) {
        var tagName = event.tagName.toLowerCase();
        if (tagName === 'dropdown') {
          if (!hasOptionChildren) {
            reporter.warn('Cannot use dropdown without providing option children.', event.line, event.col, self, event.raw);
          }
          listeningToTagsInDropdown = false;
        }
      });
    }
  });
}

@andrewbohm
Copy link

I too would love to see this feature. Do we know when this pull request will be accepted and merge? Thanks in advance!

@mike-kaufman
Copy link
Contributor

there's pending comments on teh PR that haven't been addressed, and conflicts that need resolved. Feel free to open another PR & move this forward. I'm happy to merge things in provided feedback is addressed. :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants