-
-
Notifications
You must be signed in to change notification settings - Fork 950
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to customize/override rule message text #400
Comments
Hi. @davidtheclark is in a better position to comment on how easily this can be done. But before he does, I'm curious why you'd want this functionality. Can you tell us a little more about it please? For example, if you have suggestions on how the messages could be better written, then by all means share those here, so that we can incorporate any improvements into the texts for the benefit or all the users. But if you've got a more specific use case, it'd be great to hear more about it. |
I think it would be straightforward to implement, but annoying because we'd have to change some code in all the many many many rules. But like @jeddy3, I'm curious about the use-case, because I don't think this is a typical feature of a linter and the desire isn't self-evident to me. |
@jeddy3 @davidtheclark So I think it stems from a few use-cases...
Those are just a few I could think of, but I think it would be super valuable in general. I'd be curious if you really did have to edit each rule to do this? You could possible just put it at the level where it outputs the message, and if there is a custom value in the rule set then overwrite the one in the rule? Just an idea. More or less, I think it would be extremely useful in many ways to be able to modify that rule message. |
@bluetidepro : Sound like good reasons, thanks! And you're right .... there might be some means of handling this behind the scenes without having to tweak each rule a little. So my take is it's well worth looking into but I won't be able to get to it myself for a little while. |
@davidtheclark That's fair. I can look into it and then possible add a PR if I can easily figure it out. I'll see what I can come up with! :) Thanks, David! |
I would dive in but am going backpacking tomorrow :) |
@bluetidepro Thanks for the explanation! It does sound like a worthwhile addition. Feel free to have a dig around in David's absence. @davidtheclark Have a fab holiday! :) I'll catch up with you after the 11th. |
One problem here is that many of the messages are functions, something like We could figure something out (maybe interpolation with indexed placeholders? e.g. 'No lines longer than {0}') But what this would mean is that every message would have to considered uniquely: each one may or may not pass any number of arguments. Which means for each rule we would have to somehow document how you can customize the message -- which is a big pain. Any solutions? |
Oh yeah, good point. That does significantly complicate this feature.
None from me I'm afraid. Perhaps @bluetidepro might have some ideas? I had one thought though. Perhaps it isn't an appropriate use of a formatter, but could the first two use cases be achieved using custom reporters? i.e. read the rule name from the message and then append either a link to the documentation or a friendly extra description with examples? |
Yes, a custom formatter could do any of the above. But it's not very user-friendly, of course. |
Wouldn't it make sense to start with custom messages that don't support placeholders? Our reasons are all the same as @bluetidepro mentioned earlier. With hundreds of people working on CSS, we have to explain to people what the rule is about, where to read more about it, and who to consult. So a plain message is usually enough in our case (it's just much more detailed; compare to current "no-important", for example — "Unexpected !important (declaration-no-important)" :)) |
Definitively :)
For this use case it sounds like a (private) custom formatter is probably the easiest and quickest way to get this done. You could then write extensive documentation for each rule without cluttering up your configuration file. You can also choose—on a per rule basis—whether to keep and append to the original message (with its string interpolation), or craft a new message (without any string interpolation) from scratch i.e. Is this or overwriting the messages in the config (without string interpolation for now) the best way to go? |
We could also consider creating a new feature that is just for applying custom messages --- the idea being that people could use the regular formatter but only modify messages in a straightforward way. Like, user could provide an object mapping rule names to special messages (the message could even be a function!). Let me flesh this idea out a little ... We add an option to all the APIs (plugin, standalone, CLI) for var myCustomMessages = {
'block-no-empty': 'Why would you want an empty block? Are you making a mistake?',
'max-line-length': max => `We are restricting our line length to ${max} characters ` +
`so that we can all read code in split pane editors.`
}; When a rule complains, it looks to see if there's a special message for it; if not, it uses the standard message. One limitation of this would be that you'd specify one message per rule. It assumes that you are customizing your message to your configuration, and if you change the config you'll have to remember change the message. Also, I like @jeddy3's idea of being able to append to the original message ... would like to think of a way of working that in. What do you think? |
For what it's worth, here is what I did for our (Sprout Social, where I work) use case to make our own custom messages. It's not the cleanest per se, but it's an option. We use a custom reporter in the process to have custom message outputs: https://github.com/postcss/postcss-reporter Here is a snippets with comments in the code on what's sort of going on with it: var chalk = require('chalk');
var symbols = require('log-symbols');
var _ = require('lodash');
var stylelint = require('stylelint');
var reporter = require('postcss-reporter');
// Run postcss and stylelint
var stylelintPostcss = postcss([
stylelint(),
reporter({
formatter: function(input) {
// Custom formatter to display the warnings/errors
var messages = input.messages;
var output = '';
// If there is a source, output it
if (input.source) {
output += chalk.underline(reporterLogFrom(input.source) + '\n');
}
// For each message (with content) loop the function `reporterMessagesFormat`, so lets customize how that output looks
messages.forEach(function(message) {
output += reporterMessagesFormat(message, input.source) + '\n';
})
// Ignore messages that are empty
if(!_.isEmpty(messages)){
return output;
}
},
throwError: false
})
]);
// Used in reporterMessagesFormat as a regex
var oldCodeRegexTest = /old\/components\/(.+)/;
// Ran for each message (with content)
function reporterMessagesFormat(message, source) {
// This is a regex test we do so that certain .scss/css in certain folders is considered
// an error while old code we haven't migrated yet is just a warning
var isOldCode = oldCodeRegexTest.test(source);
var str = '';
if (message.text) {
// Just get the message text
var regExp = /(.+)( \(.+\))/;
var messageText = regExp.exec(message.text);
// Get the column/line info
if (message.line && message.column) {
str += chalk.gray(message.line + ':' + message.column + ' ');
}
// Check whether we should call this an error or not
if (message.severity === 'warning' && !isOldCode) {
str += chalk.yellow(symbols.warning + ' Warning:');
} else if(message.severity === 'error' || isOldCode) {
str += chalk.red(symbols.error + ' Error:');
}
// Link to the rule so in apps like iTerm they can cmd click the link to open
// to that rule in the browser
str += ' ' + messageText[1];
if (message.rule) {
str += chalk.gray(' (' + chalk.blue('http://tiny.cc/pxoy7x/' + message.rule) + ')');
}
}
return str;
} One of my favorite parts of it is how it generated something like And the output looks like (I added some fun little stuff to the output to make it look nice too haha): So you could easily do something like this to see which rule it is ( Let me know if you have any specific questions or what to see more of the code of the full task! Hope this helps @kangax @jeddy3 @davidtheclark :) |
@bluetidepro I love it! Very good to know that the custom formatter API worked out as planned to enable something like that. |
Oh, I like this! @bluetidepro It's fantastic to see your task and the output! Up until now we've not really had the chance to see how anyone is using stylelint in their own unique way - it's awesome to see :) Like @davidtheclark said, it's also great to see the custom formatter API put to great use.
This is so cool :) It's also something I was thinking of adding to a custom formatter too!
That's kind of you. If it's not too much trouble are you able to paste into #659 the bit of the code where you tally up the total number of errors and warnings, as @s10wen was requesting exactly that feature just a couple of days ago? :) So, it looks like using a custom formatter is very much capable of fulfilling @kangax needs. Although, I think @davidtheclark's proposal compliments the custom formatter API and offers a neater solution. @kangax What are you thoughts? |
@jeddy3 No problem, I posted the full source of the grunt task here #659 (comment) |
Thanks for your thoughts, folks! The formatter is definitely the most flexible option for us. However, I also love the simplicity of solution proposed in this ticket (custom rule messages, either together with rule or in a standalone object). The thing about custom formatter is that I'll still end up writing a standalone object that maps rule names to custom messages. In your case, @bluetidepro, you were able to do a clever rule explanation via an automatically generated url (in formatter) by convention. In our case, it's probably not worth creating multiple pages for all the rules, so a simple map would be best. And considering that we're pretty satisfied with an existing formatter, we could totally do with just adding custom messages to existing rules. Should the messages be in a separate object? I'm leaning towards "not". Things in different places usually get out of sync quick and are harder to maintain. |
Allow for custom messages; closes #400
Release 4.2.0 has this feature. Give it a try! https://github.com/stylelint/stylelint/blob/master/docs/user-guide/configuration.md#custom-messages |
🎉 |
@jeddy3 Seem that it is ignored because of this general solution, so I deleted the delete result.stylelint.customMessages[ruleName]; An official way for a plugin to say, hey I'm handling custom messages by myself with support for interpolation would be great. That is my issue: AndyOGo/stylelint-declaration-strict-value#142 |
Can you create a new feature request issue for this, please? Otherwise, it'll get lost as a comment here. |
Done. |
It would be really nice if there was an easy way to customize (or override) the default rule text for each rule when you declare the rule. For example:
Output:
blah blah blah (number-leading-zero)
Where as of the default (no override), would be the normal:
Output:
Unexpected leading zero (number-leading-zero)
Is this something that can easily be done?
The text was updated successfully, but these errors were encountered: