Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Updated as of comment #16
Some things are a bit outdated and new stuff has been happening, we need to update the coding standard page https://drupal.org/node/172169. The page can be edited but we need to talk about a few things first.
We have to agree and "just" need to update the doc.
Remaining tasks
Review following changes
Following changed were approved by all 3 JS maintainers.
https://drupal.org/node/172169/revisions/view/7047917/7255245: Added strict mode section, made the wording stricter by replacing "should" by "must" where necessary so that standards align with what our JSHint configuration checks for.- DONEhttps://drupal.org/node/172169/revisions/view/7255743/7255765: Added a indication about variable naming when using jQuery.- DONE
General tasks
- Work on the wording.
Add a table of contents with #links to the top (see example at https://drupal.org/coding-standards)- DONEReplace should with must where appropriate- DONE- will be done in https://drupal.org/node/2269515
Move api-like recommendations for drupal 7 vs 8 to http://drupal.org/developing/api
The following issues are postponed on this issue:
Comment | File | Size | Author |
---|
Comments
Comment #1
jhodgdonRE idea #1 - I am not seeing the difference between the current standard and what you are proposing? They look the same to me.
RE the rest -- this is referring to what page and what paragraph? It would be a lot easier to understand what you are proposing if you put "before" and "after" sections from the page so we could compare.
Comment #2
jhodgdonOh and you forgot the tag...
Comment #3
jessebeach CreditAttribution: jessebeach commentedEvent namespaces
click.toolbar[.anothernamespace]
where additional namespaces provide an end user access to alter core Drupal functionalityExamples
click.toolbar
mouseenter.tabledrag
Comment #4
jessebeach CreditAttribution: jessebeach commentedData namespaces
referring to the jQuery.data() method.
Examples
$('div').data('toolbar', {});
$('div').data('tabledrag', {});
Comment #5
jhodgdonCan someone please update the issue summary with a list of:
a) What needs to be deleted from the current JS coding standards page.
b) What needs to be added.
c) What needs to be changed (before/after text would be helpful).
Otherwise this issue cannot really be reviewed. Thanks!
Comment #6
nod_Comment #7
nod_added #1483396-16: [policy, no patch] JavaScript coding standards for variable declarations in the doc.
I attached the text to put in the new doc page. with an interdiff.
We probably need a dedicated D8 page for them.
Current doc page is here: http://drupal.org/node/172169
Comment #8
jhodgdonI don't like the beginning of the new proposed text at all. That UL list is just ... a few hints or something? Really what is needed at the top of that page is a table of contents with #links in it so people can actually find things.
Also, the new text is written with "should" in places... does that mean things that you have to do or things that you can do if you want to? It would be better to use more precise language, such as "must", or else explain what the exceptions are.
Also, we don't normally keep different standards pages for different versions of Drupal. We just don't go back and update previous versions of Drupal to comply with standards adopted after they were released.
Comment #9
nod_Well it's NR for a reason :)
Most of the should were already there, I'm happy with changing that to must.
About the version, what happens with D7 once D8 is out? some people might still be developing D7 modules and if they try to use D8 standards well they'll have troubles. So is the page going to have footer notes D7 specific? For example we're talking about the
drupalSettings
variable in an example, that variable doesn't exist in D7.Comment #10
jhodgdonCoding standards pages are generally about code writing style (indentation, choices on how to capitalize stuff, etc.), not about which functions to use where. That information should probably be elsewhere rather than in the coding standards section, and the coding standards should not be version dependent. They should be about best practices for any version of Drupal, and should not cause problems if they are followed in a previous version of Drupal. Check the rest of the coding standards pages and I think you'll find that is the case.
Comment #11
nod_Comment #12
jhodgdonJust to clarify... In the Coding Standards section, we want to have style standards that are generally applicable. If you have programming conventions like "In Drupal 7, we do things this way, and in Drupal 8, we do things this way", the best place to put them would be somewhere in:
http://drupal.org/developing/api
Comment #13
markhalliwellFWIW, I updated the jQuery coding standards page (https://drupal.org/node/1720586). Not sure if there is actually an issue for that, so posting here.
Comment #13.0
markhalliwellup issue sum
Comment #14
YesCT CreditAttribution: YesCT commentedComment #15
YesCT CreditAttribution: YesCT commentedUpdated the issue summary to list out the standards changes, and the remaining tasks. Removing the needs issue summary update tag.
---
A.
Since we wont have a different standard for drupal 8 from others, are all these changes really wanted? Updating 6 or 7 to them might be more than we want to do.
---
I went through the diff from #7 and it seems these are the changes to the standard (the other things are changes to wording or formatting of the text of the standards doc page.
[edit: ug. used [code] and [/code] instead of < and > cause embedding code inside of code made it strange when viewing.]
change is to always have a space before the (
Why this change? Is this something other projects do? Is there a industry recommendation for this?
It seems opposing to the jQuery standard: https://drupal.org/node/1720586
https://github.com/stevekwan/best-practices/blob/master/javascript/best-... does not use the space before ( for functions
and neither do the examples in http://www.w3.org/wiki/JavaScript_best_practices#Stick_to_a_strict_codin...
I'm not sure where to look, since I'm not familiar with other projects or javascript.
and the drupal php standard:
https://drupal.org/coding-standards#functdecl
for some examples of php anonymous functions
$ ag "\->will" core/modules | grep function
and
take out allowing white space to align assignment values.
This takes out the section about allowing it, but this does not, not allow that. Maybe it should say explicitly that assignments must have only one space on either side of = ?
I didn't know this, but looks like https://drupal.org/coding-standards#functdecl
allows that white space to align assignments (for function calls??),
but that seems contradictory to the section about operators: https://drupal.org/coding-standards#operators
says not to use with, and to use (the shorthand) explicit version
is this a standard change or a code implementation recommendation? maybe this should be moved to the api docs jhodgdon mentioned in #12
Comment #16
YesCT CreditAttribution: YesCT commentedgrammar fix and adding which comment issue summary is update as of.
Comment #17
jhodgdonRE #15 - I think I agree with all the points YesCT raised. We need a new patch.
Comment #18
YesCT CreditAttribution: YesCT commentedAre #3 and #4 suggested *additions* to the js standards?
I think each change should have it's own issue so we can discuss them separately.
Maybe there can be a general wording clean up issue (which also adds table of contents) also for the changes in #7 that are not actual standards changes. So we can more easily see really what is being suggested.
Comment #19
nod_some comments
Comment #20
jessebeach CreditAttribution: jessebeach commentedI do happen to care about this one :) Mostly because I don't want to introduce a very subtle distinction into the standards like this. I'd rather the rule be uniform:
"When declaring a function, leave a space before the parenthesis; when invoking a function, no space". So
Comment #21
nod_Me too but I don't have it in me to fight it.
Comment #22
jhodgdonRE #20/21 - If leaving a space between the function declaration and the () is standard in the industry for JavaScript, let's also adopt that standard. If it's not standard, we should not adopt it here either. Can either of you provide something beyond "I care about it" and "I like it" to back this up? Do IDEs have this as their standard when declaring functions in JS? Do other projects with actual standards do it this way? Do code prettifiers have this as their default?
Because... As someone who only dabbles in JavaScript occasionally, it sure looks odd to me (especially as someone who is used to the PHP standards we have in the Drupal project). Also, what if there are function arguments between the ()?
And... Please, let's have the discussion, rather than giving up before it's hardly started (in spite of this being open for a while, there hasn't been much actual substantive discussion about the standards themselves).
And regarding #18, I think someone could do a quick edit/cleanup/add TOC pass through the standards document -- agreeing not to change any of the substance of the page -- and post a link to the revision so we could verify. Then we could use that as the starting point for proposing new standards? I don't think we need an issue for "clean up grammar, formatting, etc.", just for "this standard needs revision".
Comment #23
jessebeach CreditAttribution: jessebeach commentedSublime Text 2 auto-expands to this:
jQuery's JavaScript guidelines are just ugly. They're full of whitespace where it's not needed and lacking where it is. Plus every one of their rules (hyperbole but close) has a list of exceptions. I'd like to see us strive for consistency that doesn't require deep knowledge of the syntax -- just simple patterns.
I quite like our existing JSDocs. I'm looking out to code reviews where we're going to have to write: "Well, yes, you need a space between
function
and(
normally, but because you named your function, now you don't need a space"...over and over again. Esoteric exceptions just create friction.Comment #24
jhodgdon+1 for consistency between named and unnamed functions' whitespace, and +1 for adopting things that IDEs our developers are actually using do already by default.
And +1 for not adopting guidelines from JQuery if they're lame. If there's another set of generic JS guidelines out there we can crib, great; otherwise, let's make our own that are at least simple to understand and follow, and as consistent as possible.
So, the current standards section on functions ... dang, hard to link to. I'm going to go edit that page and add a TOC, and if I have time in my day today, I'll come back and make some more comments here. But the arguments in #23 compared to what we have now do indeed look compelling. Thanks!
Comment #25
jhodgdonOK, I just edited https://drupal.org/node/172169 and added a table of contents at the top... which really highlights the mix of topics there. Some are about the code formatting; others are about which JS built-ins to use and not use; others are about how to interact with Drupal. The next step would probably be to reorganize the page a bit more logically, and move anything there that is version-specific to a different page... but that's not really what we're discussing here.
Meanwhile, let's see. YesCT did a nice job of pointing out which items in the current standards were proposed for revising in the last patch.
The one we are discussing in the past few comments, and the only one there seems to be much disagreement about, is for declaring functions. The current standard is:
https://drupal.org/node/172169#functions
See if this is a fair assessment:
- The existing standards are inconsistent in how they are doing things in this section.
- Both jessebeach and nod_ (with some backing by IDEs) think that we should adopt a standard that results in code like this for declaring functions:
(a) is what is already in our standards doc; (b) is not, but is consistent with (a).
- The existing standards say, in words:
The proposal is to make this much simpler, something like this:
When declaring a function, there should be one space between the keyword "function" or (if it is a named function) the function name and the opening left paren "(".
Right?
To me, this seems consistent, and apparently at least one IDE agrees.
Comment #26
droplet CreditAttribution: droplet commentedIt should be also more consistency for other world parties as possible as it can. Not every contributors hired by Drupal companies and only worked for Drupal. They won't read the Code Standards until one day you're telling him: You do something WRONG!!
Can you show 3 popular IDEs example & JS libs promoted this rule. Thinking in another side, while Sublime Text do this auto-expand, why no scripts adopt it? Why guys spending more time to remove it's quick-expand styles.
No SPACE++ ( #4 ~ #6, https://drupal.org/comment/8593879#comment-8593879 )
Don't forget the Named function expression. :)
** Also don't create new rules for every Drupal version. :(
Comment #27
markhalliwell@mparker17 just posted this in IRC:
Would be worth looking into.
Comment #28
Anonymous (not verified) CreditAttribution: Anonymous commentedRe: #27, I tool around in Meteor a bit and I think they're on the money with their style guide: https://github.com/meteor/meteor/wiki/Meteor-Style-Guide
If only we could use camelCase instead of drupal_underscore_all_things... one can dream :)
Comment #29
nod_Went over the doc page, changed a few things added a section on the strict mode, changed a bit how we explain function declaration standards (thanks to sun for making that easy to explain). Changed a few "should" in "must" where appropriate and fixed syntax errors in sample code.
I think we're ready to auto-reformat stuff if there is no more complaints. We'll enforce all of this with ESLint in #2264205: Replace JSHint with ESLint for JavaScript validation It will allow us to validate our JS just like JSHint does as well as validate anything else we want it to, including JSDocs. Ideally the plan is for people to run ESLint on their code and that will tell them all they have to fix without needed to refer to the standards.
Comment #30
Anonymous (not verified) CreditAttribution: Anonymous commentedHaving read the wiki page now, I think this is looking really good. I've read around a bit about a few things I wasn't sure whether we needed (e.g. avoiding type coercion) and what struck me was just how much disagreement there can be over these things! With that in mind, I think the thing to do is just remove any ambiguities and keep it simple.
I think we should state a preference for single over double quotes (for encapsulated HTML and consistency), even though most use them anyway. Does anybody see any issues with this?
For variables, perhaps we ought to explicitly say we don't want this:
Along those lines, how about suggesting unsetting variables with null rather than undefined?
I think the if statements section should demonstrate where comments go (not at the end of lines)
One small thing that occurs to me is that there might be a few places where we could be more explicit (without being too verbose) so as to point out things which appear to be stylistic but have functional implications, e.g.
Technically, you shouldn't need === on typeof, but I suppose it could be confusing if not used all the time.
How about stating a preference for selectors as follows:
One note on this/self – to me, it would be more predictable to change this kind of thing:
To this:
This is what you find in Meteor, and it keeps things simpler. What do you think?
Should we suggest using underscore alternatives for certain things now we have it in D8, e.g. _.each? I think pushing further use of it couldn't hurt, right? Similarly, we could probably provide some advice about adding Modernizr tests to one's module/theme, rather than eschewing it for custom stuff.
Comment #31
nod_Thanks for the feedback!
Comment #32
nod_I reordered the section a little to make it faster for people familiar with JS to know which choices have been made on "troll-full" aspects of JS code style.
I added some more details on the variable. One var per line and a sentence about jQuery containaining variables names. And some code whitespace changes.
https://drupal.org/node/172169/revisions/view/7255743/7255765
Comment #33
YesCT CreditAttribution: YesCT commentedShould we update the lints also?
Or maybe lint is just for syntax errors?
Comment #34
seutje CreditAttribution: seutje commentedIf this pertains only to the changes outlined in #32, I don't have any objections. It might be nice to have some more elaboration on strict mode, but that's an extra "feature", not a bug.
The summary outlines a lot more though.
@33: Most of these will be caught by JSHint by default, especially since we enforce strict mode through JSHint. But linting is generally to avoid silly errors and things that are easily misinterpreted, coding standards are more about readability and maintainability.
Comment #35
seutje CreditAttribution: seutje commentedOne day, I will get the hang of these here dropdown widgets...
Comment #36
jessebeach CreditAttribution: jessebeach commentedAgreed to the "agreed-to"'s in the issue summary. Let's do this.
Comment #37
jhodgdonCan someone please update the issue summary to summarize what policy has been or is being agreed to on this issue? It is hard to review when the issue summary is not updated.
Such as, it says "Agree to ... standard" but it doesn't say what that standard is, where to find the updated page in the summary, or if it's just an edit of the existing page, what revision diff we should be looking at. Thanks!
Comment #38
nod_Comment #39
nod_updated summary
Comment #40
sunIn general, this looks good to me.
Implanted IETF/RFC keyword terminology: https://drupal.org/node/172169/revisions/view/7255765/7271425
Summary of my review:
A high-level concern from my side is that the document mixes coding style standards with best practices in various locations. The most prominent example is the chapter about
eval()
, which has nothing to do with code style/formatting.This causes the scope and purpose of the document to get fuzzy. Based on my experience with coding standards, such mixing tends to cause confusion for future discussions and updates, because people (reasonably) cannot understand what parts of the document are about formatting and which are about "recommended practice for authoring JS code in Drupal".
The IETF/RFC terminology helps to mitigate that by making clear what's required and what isn't (MUST vs. SHOULD vs. RECOMMENDED vs. MAY), but it does not help to clarify the scope.
I would recommend to split the best practices into a separate document.
The document additionally contains multiple explanations of basic JavaScript language constructs. Those are definitely off-topic for a coding style/formatting document. And even in a separate best practices document, I would still not understand why we're trying to educate about JavaScript essentials on our own...
The most prominent example is the note that Booleans must be written in lowercase in JavaScript, because uppercase… — Such documentation does not make sense, because it documents the JavaScript language itself. If you write invalid JavaScript code, your code blows up. End of story.
I would recommend to remove those parts altogether without replacement.
Some more granular items:
"use strict";
should be added to every function, or whether a single declaration per file/closure is sufficient.The meaning of "constants" could be clarified, because there is/was no such thing until very recently.
ECMAScript 6 introduced the
const
keyword, but it isn't supported on all browsers yet.Regardless of the usage aspect, the proposed standard of using lowerCamelCase for constants comes very unexpected. In the vast majority of programming languages, constants are declared as UPPER_UNDERSCORED.
Especially when writing backwards-compatible code, you have to use
var
instead ofconst
, and the common norm is that an all-uppercase variable name denotes that its value is supposed to be read-only.I would recommend to adjust the standard for constant names to say that they SHOULD be in all-uppercase, words separated by underscores.
The chapter about "Typeof" needs revision. Not even I was able to make sense of the intended meaning, or what exactly it tries to say/rule.
I expected it to talk about the comparison value (e.g.,
=== 'undefined'
vs.== undefined
), but it only talks about the value/expression that is being tested — which makes little to no sense, because if you wrap the value to be tested into a string, then its type is always a string.I've personally been a fan of doing that back in 2006. But in the meantime, I've experienced way too many patches that had to touch a dozen of unrelated lines, just to adjust the vertical alignment of variable assignments, in case a new variable had a longer name, or in case the longest variable name was removed or shortened.
That's not only cumbersome for developers — worse, it additionally tampers git's native content change tracking + pickaxe facility with unnecessary changes. If you pickaxe for a variable name that is vertically aligned, then you commonly get a completely useless resulting list of commits that only added or removed some spaces on the declaring line. Coding standards SHOULD NOT work against useful history parsing tools.
I would recommend to either drop this statement, or perhaps even reverse it into "SHOULD NOT be vertically aligned".
The "Comments" chapter uses weird terminology:
All code comments are documentation, so the terminology used is illogical.
I assume that "non-documentation" tries to refer to JSDoc blocks…? If that is the intended meaning, then we should replace those instance with the proper terminology.
That said, only a small part of this chapter is within the scope of coding style/formatting. The parts about how & why should be moved to the separate + preexisting document about JavaScript documentation.
Comment #41
markhalliwellI generally agree with sun's statement sin #40.1 and #40.2.
I think to help all of us understand which are "rules" (MUST [NOT]), which are "standards" (SHOULD [NOT]) and which are "best practices" ([NOT] RECOMMENDED) we should prefix lines appropriately (see below). We can then worry about splitting things up accordingly later.
FYI, anything in blockquotes is my "rewrite" (doing it here so we can discuss/approve before making changes). I'm only doing the first few sections (mainly due to time) but also to see if this is the format we'd like to present (which I think is much clearer). Here's a link to this comment's HTML if anyone wants to update the page with what I've done: http://privatepaste.com/0a717dc5fe
I'll have to go through the rest of the sections when I get more time.
Whitespace (formerly "Indenting")
I also think the Function Calls (under Functions) should be moved to this section as they deal entirely with whitespace.
Semi-colons
Closures/Strict mode
I think these two can be combined really. Also there appears to be nothing about closures in general on the page. I'm not entirely sure how we want to go about this. Leaving for discussion.
Comment #42
nod_Agreed with #40.1 and #40.2 it was probably useful once but nowdays it's the wrong place for those things. I'll work on it today.
Comment #43
nod_updated coding standard page and created a javascript best practice page to put all the stuff that didn't have it's place in the CS doc.
Diff for CS page: https://www.drupal.org/node/172169/revisions/view/7271425/7404721
new doc page: https://www.drupal.org/node/2297057
Comment #44
jhodgdonCoding standards changes are now part of the TWG
Comment #45
xjmFor now I added a note on the main coding standards page https://www.drupal.org/node/172169/revisions/view/8038301/8400517 since it was pretty buried and non-obvious.
Comment #46
nod_The rules in the JS coding standards are done. The wording and all can be improved, sure, but the rules themselves don't need discussion anymore.
The JS documentation standards are not done yet.
Comment #47
droplet CreditAttribution: droplet commentedWhat's the code standard for data-* attributes ? Can we skip `drupal` namespace ?
Comment #48
nod_I'd like to keep it, and fix everything that's not using it already.
I know it's kind of ugly but we just can't predict what some JS lib will get out in the future that would use
data-default-value
,data-date-formatter
or the other things we're using and could be very confusing. Making it predictable with adrupal
prefix helps in case we need to filter out all drupal-related things from HTML for example. We can discuss that in #1090592: [meta] Use HTML5 data-drupal-* attributes instead of #ID selectors in Drupal.settings though, If there is a case for it, we could get rid of it.Comment #49
DamienMcKennaGetting a little meta, but how does the process being defined in #2428153: Create and document a process for updating coding standards affect this proposal?
Comment #50
frobWhat is left to do here. Can someone update the issue summary?
Comment #51
droplet CreditAttribution: droplet commentedI'd suggest to fork this page as our standard:
https://github.com/airbnb/javascript/tree/master/es5
- this is about 99.8% of what we needed and even better.
- we just need to update a bit `Whitespace` rule in function
- add back for-in suggestions
Comment #52
tizzo CreditAttribution: tizzo commentedMoving this issue to the Coding Standards queue per the new workflow defined in #2428153: Create and document a process for updating coding standards.
Comment #53
frob@droplet, why not do the fork and make the change so we can review? I skimmed the page it looks good.
Comment #54
droplet CreditAttribution: droplet commentedCheck it out:
https://github.com/KayLeung/javascript/tree/master/es5
Compare it to Airbnb master:
https://github.com/airbnb/javascript/compare/master...KayLeung:master
Pull requests are welcomed!
Comment #55
markhalliwellUm... why are we forking airbnb? @nod_ has already gone through all of this (see issue summary and related issues). AFAIK, there's not really left to do... but I could be mistaken.
Comment #56
nod_Cleaner presentation? I don't mind, whatever people prefer. Almost everything is checked by ESlint now so no big problem changing things up if that helps.
Comment #57
droplet CreditAttribution: droplet commentedDon't make something never-end :)
We have to introduce great resource into Drupal and solve the problem. Same to this idea: #2289619: Add a new framework base theme to Drupal core
It seems a bit late in D8 JS now, but if we looking at other style guide, all has no spaces in function expressions:
https://github.com/jscs-dev/node-jscs/tree/master/presets
Comment #58
frobSo what are the JS Coding standards? The official doc pages are marked out of date with a link to this issue. From reading this issue all I see is an ES lint definition and a (possibly) good js doc standards page that was forked from airbnb.
What are the current standards?
Comment #59
droplet CreditAttribution: droplet commentedES6 is not so far there. It's coming tomorrow. Just today we see WebKit hit 100% ( https://news.ycombinator.com/item?id=11708840 ). Coding Guide should be defined before it's come true I think. Forking airbnb, we will save another 4 years for the wording.
For next 4 years, we should try to do this: https://angular.io/docs/ts/latest/guide/style-guide.html
A guide for better extending of JS code in Drupal.
Comment #60
frobPersonally, I think we would do better to have our official coding standards on drupal.org. My question is more around what the coding standards are.
Do we have one? Should I just copy everything from the Airbnb fork over to d.o? I can update the d.o doc page. I just want to know what to take the standards from.
Comment #61
pfrenssenComment #62
pfrenssenComment #63
pfrenssenI checked all comments in this issue, and all proposed issues have been addressed and are published. The last on topic comment was in #46 but this has also been addressed in the meanwhile in #1337022: [policy, no patch] Create/adopt JavaScript docs standards compatible with a JS documentation parser.
Starting from comment #47 we had a couple of specific suggestions but these are out of scope for this issue. It seems like these suggestions were posted here mainly because the JS coding standards page currently links to this issue.
In particular there has been a suggestion from @droplet to replace our entire JS coding standards by the one from Airbnb, but this is out of scope for this issue. The goal was not about throwing out our current coding standard and rewriting it from scratch, but simply to clean up the coding standards page and bring it up to date with the current standard that emerged in core over the past years. If desired a new issue can be opened to discuss this, but it seems to me that this would be considered too disruptive to be accepted by the community.
I compared the coding standards page with the version from 2012 and it has vastly improved. In fact there are only few paragraphs left that have not been touched in the lifetime of this issue. Overall it looks pretty good now.
There doesn't seem anything left to do here. There will always be small things to improve, but we can tackle these in separate followup issues.
Removing the "work in progress" notice from the documentation page and marking this issue as fixed. Please feel free to open followup issues to propose specific improvements.
Comment #65
droplet CreditAttribution: droplet commentedWe should not close the issue in this way :)
the adoption from Airbnb (presentation) implies we can adopt the ES2005+ to Drupal also. I don't think we should waste any time on a new issue.
Comment #66
jthorson CreditAttribution: jthorson as a volunteer commentedHandling that discussion in a dedicated issue allows for a more efficient discussion, where participants don't need to read and sort through fifty comments, some up to four years old, in order to determine the actual context for the discussion.
Also, while the ES5 proposal is to update the our coding standards *policies*, the spirit of this issue was to update our coding standards *documentation*; which is a different scope.
Comment #67
nod_The issue is here :) #2815077: Adopt airbnb javascript style guide v14.1 as new baseline javascript coding standards for Drupal 8 core and contrib.