Problem/Motivation

We have extensive standards for how to document PHP functions, classes, etc. on http://drupal.org/node/1354

We have some standards for how to write JavaScript code on http://drupal.org/node/172169 -- and if you search for the "Comments" section on that page, you will see that it says to use the above PHP documentation standards for JavaScript.

However:
- We don't have a parser to read that type of documentation and display it on api.drupal.org for JavaScript. There's a separate issue about that: #25901: Parse/save/display JavaScript files
- If we adopt a JS doc parser, probably our Drupal-Doxygen comments will not be parsed correctly by this parser without some modification.
- The Drupal Core JavaScript code mostly lacks these documentation headers currently anyway.

Proposed resolution

- Choose a documentation parser for JavaScript. [Currently, there are no viable candidates, so this issue has been postponed -- see #25901: Parse/save/display JavaScript files.)
- Decide on a standard for JavaScript function/class/etc. docs headers. It should be similar to our standards for PHP, but parseable by this parser.
- Verify that this works for parsing by this parser.
- Write a standards page for Drupal JS doc headers.
- Work towards getting the existing Drupal JS code in compliance.

Remaining tasks

Everything listed above is TBD.

User interface changes

None.

API changes

New docs standards for JavaScript in Drupal would be adopted, where essentially none existed before.

Files: 
CommentFileSizeAuthor
#74 out.txt166.79 KBjhodgdon
#72 jsdoc.js_.txt1.84 KBnod_
#72 jsdoc.json_.txt8.11 KBnod_
#72 publish.js_.txt398 bytesnod_
#33 namespaces.png68.83 KBjhodgdon
#33 1337022-partial-namespaces.patch9.19 KBjhodgdon
PASSED: [[SimpleTest]]: [MySQL] 36,663 pass(es). View
#19 1337022-partial.patch9.2 KBjhodgdon
PASSED: [[SimpleTest]]: [MySQL] 36,660 pass(es). View

Comments

jhodgdon’s picture

Issue tags: +coding standards

forgot tag

jhodgdon’s picture

By the way, this is all the JS standards page has to say about docblocks currently:

Inline documentation for source files should follow the Doxygen formatting conventions.
(with a link to node/1354)

jhodgdon’s picture

And here is the tag reference for JSDoc, which is basically all the documentation I have found:
http://code.google.com/p/jsdoc-toolkit/wiki/TagReference

I'm still unsure where they expect the comments to be placed, and whether our standard docblocks would be parsed?

ksenzee’s picture

The rest of that wiki seems to have some useful examples. I gather from the jsdoc users group that JSDoc version 3 is under development at https://github.com/micmath/jsdoc.

jhodgdon’s picture

Really? I didn't see any examples like "Here's a good way to document a function, params, and return value" types of things?

Thanks for the link to jsdoc v. 3 - added to that API module issue.

eric.duran7@gmail.com’s picture

hmm, v3 might be the way to go. Testing it out.

eric.duran7@gmail.com’s picture

If we're going to use jsdoc, I think we should adopted their coding standards for JS at least.

They have a site up at http://usejsdoc.org/ is seems to also be under development with the 3.x version.

Something to consider.

sun’s picture

Title: No standards exist for docblocks for JavaScript » Adopt JavaScript JSDoc standards
Category: bug » task
RobLoach’s picture

Issue tags: +JavaScript

Oh yes.

jhodgdon’s picture

Ugh. I took a look at http://usejsdoc.org/ today.

It looks like their standard function header would be something like this:

    /**
        Represents a book. [sic]
        @constructor
        @param {string} title - The title of the book.
        @param {string} author - The author of the book.
     */
    function Book(title, author) {
    }

This to me is not very human-readable. So it would be good to know if we can format it more like our PHP standards and still have the JSDoc parser recognize it and create good documentation... something like this:

    /**
      * Constructs a book.
      *
      * Longer description goes here, and it could run to a few lines. Here is
      * a second line.
      *
      * @constructor
      *
      * @param {string} title
      *    The title of the book.
      * @param {string} author
      *   The author of the book.
     */
    function Book(title, author) {
    }

Note: maybe it needs - between the parameter name and the description? There is no doc yet for the @param tag on that site, and the V2 doc says no:
http://code.google.com/p/jsdoc-toolkit/wiki/TagParam

nod_’s picture

Any new opinions about this? i'll be working on js code standards soon, see also #625926: jQuery coding standards.

sun’s picture

ugh. http://usejsdoc.org/ is more bizarre than I could have ever imagined.

It looks like the author(s) don't have any experience with code documentation parsers and existing code documentation standards.

The JSDoc "standard", as visible over there, entirely lacks a generic pattern, consistency, and also compatibility with other documentation standards and parsers.

Since this issue is specifically about adopting "the" JSDoc standard, and since http://usejsdoc.org/ seems to aim towards taking away the JSDoc term, I'm tempted to call this issue won't fix.

jhodgdon’s picture

Title: Adopt JavaScript JSDoc standards » Create/adopt JavaScript docs standards compatible with JSDoc parser

True, it's not a standard by any useful definition.

So what we need to do is adopt a docs standard that is compatible with the JSDoc parser, or one compatible with any other JavaScript doc parser we can find (but as far as I know, this is the only one being currently maintained).

nod_’s picture

The always awesome YUI is using javadoc and a custom parser to make their doc: https://github.com/yui/yuidoc/blob/master/TAGS

End it seems like a script exists for doxygen. and I ran into this one as well: https://wiki.appcelerator.org/display/tis/ScriptDoc+(SDOC)+2.0+Specification

What are we using for our PHP exactly?

(edit) But unless we have a strategy for stripping comments i wouldn't recommend commenting our JS files at all. It'll makes them way to heavy.

jhodgdon’s picture

We are using the API module http://drupal.org/project/api to do PHP docs.

attiks’s picture

jhodgdon’s picture

Thanks attiks, issue summary updated with current link.

jhodgdon’s picture

Status: Active » Postponed (maintainer needs more info)

I tested the JSDoc parser on our current JS code (Drupal 7 code base, misc directory) today. Full results are at:
http://drupal.org/node/25901#comment-6022812

Executive summary: No output was produced. I don't think JSDoc wants to produce documentation for Drupal.behaviors.* variables, no matter how we document them. So unless someone can figure out how to instrument our Drupal source code so that JSDoc wants to recognize that Drupal.behaviors.* should be documented, adopting "standards" like what JSDoc would use is not going to do us much good.

If anyone has experience with JSDoc or can figure out what we'd need to do, please comment here or on that other issue... until then, I don't think there is much use in keeping this issue in "active" status.

jhodgdon’s picture

Status: Postponed (maintainer needs more info) » Needs review
FileSize
9.2 KB
PASSED: [[SimpleTest]]: [MySQL] 36,660 pass(es). View

Aha! I managed to get JSDoc to work, with some hints from several other Drupalists and the JSDoc issue queue.

So... Here is a proposed standard for JavaScript docs, and the beginnings of a patch (I only patched a couple of the JS files in Drupal 8). This standard/patch would make us compatible with JSDoc and, hopefully soon, the API module.

---

JavaScript classes, functions, methods, and variables should be documented with documentation headers that are very similar to the PHP documentation headers described in http://drupal.org/node/1354 . Follow the standards described there, with the following changes:

  • All JavaScript items (methods, classes, functions, variables, etc.) need to have documentation headers, or they will not be recognized at all by the parser (unlike the API module, which picks up all PHP items whether or not they have documentation headers).
  • Not all of the @tags we use for PHP are supported. Just use @param, @return, @see, @link, @code, and @throws.
  • The equivalent tag to @file is @fileOverview.
  • To indicate the type for a @param or @return tag, put the type in {} brackets: @param {TheType} paramName or @return {TheType}.
  • Some additional notation is required in most cases to help JSDoc figure out what type of item is being documented: use @lends Drupal before a JQuery closure to indicate that everything within belongs to the Drupal class, and use @class to indicate that a particular function documentation block is actually for a class or class constructor. Here's a sample (from Drupal 7's misc/autocomplete.js):
    /**
     * @fileOverview JavaScript for auto-complete form fields.
     */
    
    /**
     * @lends Drupal
     */
    (function ($) {
    /**
     * Attaches the autocomplete behavior to all required fields.
     *
     * @class
     */
    Drupal.behaviors.autocomplete = {
      /**
       * Attaches the behavior.
       */
      attach: function (context, settings) {
           ...
      }
    };
    
    };
    
    /**
     * Handles submission of the auto-complete form.
     *
     * Prevents the form from submitting if the suggestions popup is open
     * and closes the suggestions popup when doing so.
     */
    Drupal.autocompleteSubmit = function () {
    ...
    }
    
    /**
     * Represents an auto-complete object.
     *
     * @class
     */
    Drupal.jsAC = function ($input, db) {
    ...
    }
    
    /**
     * Handles the "keydown" event.
     */
    Drupal.jsAC.prototype.onkeydown = function (input, e) {
    ...
    }
    
  • ----

attiks’s picture

Status: Needs review » Needs work

Some questions:

  1. why not use @file instead of @fileOverview
  2. @code isn't supported out of the box, they use @example. But 'someone' can always create a plugin
attiks’s picture

Status: Needs work » Needs review
jhodgdon’s picture

RE #20

RE @file - yes you are right -- I just found the new tag reference for version 3, and they do support @file as a synonym. So yes, we should stay with @file instead of @fileOverview.

RE @code - that will be supported in the API module code. @example in JSDoc is not the same thing -- that has to be a separate docblock I think -- whereas @code can be put inside other docblocks.

jhodgdon’s picture

There is a relevant comment about standards from nod_ at:
https://drupal.org/node/25901#comment-6027592
(and next comment from ksenzee to follow-up)...

The essence is that we might not want to call the Drupal object (and Drupal.behaviors etc.) a "class", as it's more properly an object or namespace, and some of the other items are more properly constructors (although if you look at the JSDoc documentation, you'll see that @class really means "what follows is a class constructor).

So maybe the standard/patch in #19 needs some more revision... Anyway, JSDoc supports @namespace and @class, so we should be able to do either one.

ksenzee’s picture

unless we have a strategy for stripping comments i wouldn't recommend commenting our JS files at all

If our JS isn't commented, the community will be unable to maintain it, and unmaintained code will eventually cease to be useful. (I suppose at that point we could just throw it out, which would fix the code weight problem!) Seriously, we should be dealing with code weight by minifying our JS, over at #119441: Compress JS aggregation.

nod_’s picture

total +1 on #24

nod_’s picture

copying the reply from #25901-57: Parse/save/display JavaScript files

yes I agree that it's close enough to a class, It's not though. Assimilating the two just demonstrate how people don't get the difference between classes and objects. As far as behaviors are concerned, namespace is much better indeed.

In the example you're giving, what should be documented? the x or the Y? One is an object and the other is a constructor I don't see any ambiguity as far as I'm concerned. Declaring something as a Class means we have a coherent declaration that uses some wrapper to extend the constructor behind the scene so that the "class" declaration fits in one object, much like YUI does it. It can be confusing for other devs but is it worth the confusion? I'm not convinced.

The js needs some refactoring, that's when we could introduce some class concepts that would fit well with jsdoc.

ksenzee’s picture

Responding to #25901-57: Parse/save/display JavaScript files in this issue as jhodgdon requested.

yes I agree that it's close enough to a class, It's not though. Assimilating the two just demonstrate how people don't get the difference between classes and objects. As far as behaviors are concerned, namespace is much better indeed.

In the example you're giving, what should be documented? the x or the Y? One is an object and the other is a constructor I don't see any ambiguity as far as I'm concerned. Declaring something as a Class means we have a coherent declaration that uses some wrapper to extend the constructor behind the scene so that the "class" declaration fits in one object, much like YUI does it. It can be confusing for other devs but is it worth the confusion? I'm not convinced.

The js needs some refactoring, that's when we could introduce some class concepts that would fit well with jsdoc.

Are you saying that just because Drupal.verticalTab.prototype.focus is declared later on in the file, Drupal.verticalTab doesn't count as a class? If so I don't really agree. Take misc/vertical-tabs.js as an example. Drupal.verticalTab is a constructor. I see no reason not to include @class in its docblock:

/**
 * The vertical tab object represents a single tab within a tab group.
 *
 * @class
 *
 * @param settings
 *   etc. etc.
 */
Drupal.verticalTab = function (settings) {
 ...
};

Sure, methods get added to its prototype separately, but in my mind that doesn't preclude it from being a class. To me a class has a constructor, properties, and methods, and you instantiate it.

nod_’s picture

That's one of my issue with JSdoc, @class is an alias of @constructor, so basically, at JS doc level it's the same. That does not make a lot of sense to me.

(edit) In this vertical tabs example, Drupal.verticalTab is a function, so it's an object and because we're adding things to this object's prototype it's now a *useful* constructor. I'm not making this stuff up, I'm merely referring to the JS spec: http://ecma-international.org/ecma-262/5.1/#sec-4.3.4

jhodgdon’s picture

Status: Needs review » Needs work

OK... So let's think about this a bit. What type of thing (object? namespace? class? method? function? property? something else?) should each of these ideally be? [In this list, I've put {} after each item that is declared as an object, and () after each item that is declared as a function.]

Drupal {}
Drupal.attachBehaviors()
Drupal.behaviors {}
Drupal.settings {}
Drupal.locale {}
Drupal.ajax {}
Drupal.ajax.prototype.keypressResponse()
Drupal.behaviors.AJAX {}
Drupal.behaviors.AJAX.attach()
Drupal.ajax.prototype.commands {}
Drupal.ajax.prototype.commands.insert()

My rather old copy of the O'Reilly "JavaScript: The Definitive Guide" says "An object is a collection of named values. These named values are usually referred to as the properties of the object." ... "Objects are created with the new operator. This operator must be followed by the name of a constructor function that serves to initialize the object." ...[an example of this] "We have defined a class of objects simply by defining an appropriate constructor function." ... "A method is nothing more than a JavaScript function that is invoked through an object."

The JSDoc documentation at http://usejsdoc.org/ further says that @class means "This function is intended to be called with the new function."

So... Really, JavaScript doesn't have a formal thing called a "class". It just has objects, and if you declare a constructor function foo and call it with var x = new foo(), you have just instantiated what you might call "class foo".

My old JavaScript book doesn't discuss namespaces, but I found
http://elegantcode.com/2011/01/26/basic-javascript-part-8-namespaces/
which basically says that the language doesn't have a formal namespace concept, but you can pretend it does by putting all of your functions and variables into a single global object (as we do with the Drupal and Drupal.behaviors objects).

So... I guess I am agreeing with nod_ and ksenzee: I think anything that has a constructor function, we should call a class, and things like Drupal and Drupal.behaviors, we should just call namespaces.

I'll do a bit of experimenting to see if JSDoc supports nested namespaces, and propose a new standard and patch if it does.

jhodgdon’s picture

correction: maybe nod_ doesn't agree with my statement about "anything with a constructor is a class"... anyway, I think that's what the references I have say...

ksenzee’s picture

I don't see anything in the spec that keeps us from using the term "class" to refer to objects like Drupal.verticalTabs. But I also don't mind using @constructor to describe constructors if that makes everyone happy.

nod_’s picture

As far as the spec is concerned I can't see anywhere where they describe how to create a class, they do have a name for all the constructs we're seeing here though.

I don't know about everyone but @constructor would make me happy at least.

jhodgdon’s picture

FileSize
9.19 KB
PASSED: [[SimpleTest]]: [MySQL] 36,663 pass(es). View
68.83 KB

Yeah, this works just fine. Attached is a patch covering drupal.js, autocomplete.js, and ajax.js (they could all use some param/return tags though!), and a screen shot of what the JSDoc HTML output looks like (it won't be quite the same in the API module, but it at least demonstrates that it parses OK).

New standards proposal:

---

JavaScript code should be documented with documentation headers that are very similar to the PHP documentation headers described in http://drupal.org/node/1354 . Follow the standards described there, with the following changes:

  • All JavaScript items (methods, object constructors and properties, functions, variables, etc.) need to have documentation headers, or they will not be recognized at all by the parser (unlike the API module, which picks up all PHP items whether or not they have documentation headers).
  • Not all of the @tags we use for PHP are supported. Just use @file, @param, @return, @see, @link, @code/@endcode, and @throws.
  • To indicate the type for a @param or @return tag, put the type in {} brackets: @param {TheType} paramName or @return {TheType}.
  • Some additional notation is required in most cases to help JSDoc figure out what type of item is being documented:
    • Use @lends Drupal before a JQuery closure to indicate that everything within belongs to the Drupal namespace
    • Use @class to indicate that a particular function documentation block is actually for a class constructor, and within that, add a line starting with @classdesc that describes the class itself.
    • Use @namespace to indicate that a particular object is being used as a namespace.

Here's a sample (from Drupal 7's misc/autocomplete.js):

/**
 * @file JavaScript for auto-complete form fields.
 */

/**
 * @lends Drupal
 */
(function ($) {
/**
 * Attaches the autocomplete behavior to all required fields.
 *
 * @namespace
 */
Drupal.behaviors.autocomplete = {
  /**
   * Attaches the behavior.
   */
  attach: function (context, settings) {
       ...
  }
};

};

/**
 * Handles submission of the auto-complete form.
 *
 * Prevents the form from submitting if the suggestions popup is open
 * and closes the suggestions popup when doing so.
 */
Drupal.autocompleteSubmit = function () {
...
}

/**
 * Constructs an autocomplete object.
 *
 * @class
 * @classdesc Represents an autocomplete object.
 */
Drupal.jsAC = function ($input, db) {
...
}

/**
 * Handles the "keydown" event.
 */
Drupal.jsAC.prototype.onkeydown = function (input, e) {
...
}

----

jhodgdon’s picture

We can adopt @constructor instead of @class in the proposed standard in #33 if you think it would be clearer. I'm happy either way. With the @classdesc in there, it becomes clearer what is being documented, I think...

jhodgdon’s picture

Status: Needs work » Needs review

And I guess the sample in the standard should also have @param and @return added to it. :) Other than that, what do you think?

jhodgdon’s picture

RE #32 - there really isn't anything in JavaScript that you can define as a "class", I think? But any function that can be invoked with new and creates an object is a constructor, and defines what is informally known as a "class" in my JavaScript reference... So fine, let's use @constructor instead of @class as the tag. Really, either way is fine.

ksenzee’s picture

Right. The internal [[Class]] property does seem to be used that way -- instances of Boolean get a [[Class]] of "Boolean", for example -- but there's no definition of a "class" in the spec. It's just an informal but useful way to refer to things like Drupal.verticalTab (which should really be Drupal.VerticalTab, but I digress). Sounds like @constructor is the consensus.

nod_’s picture

Indeed with the change from @class to @constructor it looks great to me.

One big thing left is custom events documentation (tabledrag.js has one custom event at least "columnschange").

(The Uppercase first letter for constructors is on the plate once a few other patches go through :)

attiks’s picture

Regarding events you can use @event and @fires

nod_’s picture

yep, just pointing out it's missing from the proposal in #33

jhodgdon’s picture

Good ideas! Although I'm not sure about @event -- it is documented at http://code.google.com/p/jsdoc-toolkit/wiki/TagEvent (which is the previous version of JSDoc) to indicate a function handles an event of the same name. But it looks like our functions are things like "onkeyup" for an event like "keyup", at least in autocomplete.js... maybe we don't need to worry about that?

Meanwhile, here's a new standards proposal (I haven't updated the patch):
---

JavaScript code should be documented with documentation headers that are very similar to the PHP documentation headers described in http://drupal.org/node/1354 . Follow the standards described there, with the following changes:

  • All JavaScript items (methods, object constructors and properties, functions, variables, etc.) need to have documentation headers, or they will not be recognized at all by the parser (unlike the API module, which picks up all PHP items whether or not they have documentation headers).
  • Not all of the @tags we use for PHP are supported. Of the tags mentioned on http://drupal.org/node/1354, only use @file, @param, @return, @see, @link/@endlink, @code/@endcode, and @throws.
  • Like @throws, which documents exceptions being thrown by a PHP or JavaScript function, use @fires to document events that are triggered by a JavaScript function.
  • To indicate the type for a @param or @return tag, put the type in {} brackets: @param {TheType} paramName or @return {TheType}.
  • Some additional notation is required in many cases to help JSDoc figure out what type of item is being documented. Add tags to the bottom of the documentation block, as follows:
    • Use @lends Drupal before the start of a JQuery closure to indicate that everything within belongs to the Drupal namespace.
    • Use @constructor to indicate that a function is intended to be a class constructor. Immediately after the @constructor line (at the bottom of the documentation block), add a line starting with @classdesc to describe the purpose of the class that is being constructed by this constructor.
    • Use @namespace to indicate that an object is intended as a namespace.
    • Use @event to indicate that a function responds to an event of the same name.
    • You do not need to use @function though - JSDoc will assume anything declared as a function is a regular function or method, unless one of the tags above overrides this determination.

Here's a sample:

/**
 * @file JavaScript for auto-complete form fields.
 */

/**
 * @lends Drupal
 */
(function ($) {
/**
 * Attaches the autocomplete behavior to all required fields.
 *
 * @namespace
 */
Drupal.behaviors.autocomplete = {
  /**
   * Attaches the behavior.
   *
   * @param context
   *    Something describing the context parameter.
   * @param settings
   *    Something describing the settings parameter.
   */
  attach: function (context, settings) {
       ...
  }
};

/**
 * Handles submission of the auto-complete form.
 *
 * Prevents the form from submitting if the suggestions popup is open
 * and closes the suggestions popup when doing so.
 */
Drupal.autocompleteSubmit = function () {
...
}

/**
 * Constructs an autocomplete object.
 *
 *  (add @param descriptions here)
 *
 * @constructor
 * @classdesc Represents an autocomplete object.
 */
Drupal.jsAC = function ($input, db) {
...
}

/**
 * Handles the "keydown" event.
 *
 * (add @param descriptions here)
 *
 * @event
 */
Drupal.jsAC.prototype.onkeydown = function (input, e) {
...
}

----

attiks’s picture

jhodgdon’s picture

I see @fires there, but not @event.

jhodgdon’s picture

Duh. I am apparently unable to see... so that looks like you have to put @event on a line of code, not in another docblock, and it can be followed by the name of an event? It would sure be nice if they had some documentation on this stuff. Sigh.

jhodgdon’s picture

Also it looks like they are using @event not as it is documented in the old JSDoc tag reference. There it says you use @event to tag a function that *responds* to an event. Here, they are using it on the line that *fires* the event.

jhodgdon’s picture

Sorry for all the comments here. I did some testing, and it appears that the code sample at https://github.com/jsdoc3/jsdoc/blob/master/test/fixtures/eventfirestag.js is right (i.e., it documents the current behavior of JSDoc), and the old documentation is either wrong or obsolete. We can't really use @event for anything useful IMO. It is used right before a line of code where the event is fired, not as an indication that a function is an event handler.

So... one more go at standards:

---

JavaScript code should be documented with documentation headers that are very similar to the PHP documentation headers described in http://drupal.org/node/1354 . Follow the standards described there, with the following changes:

  • All JavaScript items (methods, object constructors and properties, functions, variables, etc.) need to have documentation headers, or they will not be recognized at all by the parser (unlike the API module, which picks up all PHP items whether or not they have documentation headers).
  • Not all of the @tags we use for PHP are supported. Of the tags mentioned on http://drupal.org/node/1354, only use @file, @param, @return, @see, @link/@endlink, @code/@endcode, and @throws.
  • Like @throws, which documents exceptions being thrown by a PHP or JavaScript function, use @fires to document events that are triggered by a JavaScript function.
  • To indicate the type for a @param or @return tag, put the type in {} brackets: @param {TheType} paramName or @return {TheType}.
  • Some additional notation is required in many cases to help JSDoc figure out what type of item is being documented. Add tags to the bottom of the documentation block, as follows:
    • Use @lends Drupal before the start of a JQuery closure to indicate that everything within belongs to the Drupal namespace.
    • Use @constructor to indicate that a function is intended to be a class constructor. Immediately after the @constructor line (at the bottom of the documentation block), add a line starting with @classdesc to describe the purpose of the class that is being constructed by this constructor.
    • Use @namespace to indicate that an object is intended as a namespace.
    • You do not need to use @function though - JSDoc will assume anything declared as a function is a regular function or method, unless one of the tags above overrides this determination.

Here's a sample:

/**
 * @file JavaScript for auto-complete form fields.
 */

/**
 * @lends Drupal
 */
(function ($) {
/**
 * Attaches the autocomplete behavior to all required fields.
 *
 * @namespace
 */
Drupal.behaviors.autocomplete = {
  /**
   * Attaches the behavior.
   *
   * @param context
   *    Something describing the context parameter.
   * @param settings
   *    Something describing the settings parameter.
   */
  attach: function (context, settings) {
       ...
  }
};

/**
 * Handles submission of the auto-complete form.
 *
 * Prevents the form from submitting if the suggestions popup is open
 * and closes the suggestions popup when doing so.
 */
Drupal.autocompleteSubmit = function () {
...
}

/**
 * Constructs an autocomplete object.
 *
 *  (add @param descriptions here)
 *
 * @constructor
 * @classdesc Represents an autocomplete object.
 */
Drupal.jsAC = function ($input, db) {
...
}

----

ksenzee’s picture

We can't really use @event for anything useful IMO. It is used right before a line of code where the event is fired

Actually this sounds like exactly what we need for custom events that we trigger.

jhodgdon’s picture

But we can just put @fire in the doc header of the function that fires it... why do we need @event, which apparently has to go in the middle of a function where the event is actually fired? This doesn't make sense to me...

nod_’s picture

with fire you can document which event you're fireing but you have no clue about what this event is supposed to be. And I wouldn't want to duplicate the explaination of an event all over the place.

I see @fire as a way to say: ok inside this method, somewhere, somehow this event is being fired. From that you can build a list of all the methods that fire this event (very much like a "module implementing this hook" kind of thing). But you still have no clue about what that event is supposed to be (when is the hook supposed to be fired, what is the overall context, parameters?) and that should be documented with @event.

At least that's how I understand jsdoc.

(edit) And I just wanted to add that I'm really happy you're taking the time to learn some things about JS for this, thanks a lot!

jhodgdon’s picture

OK, so you're saying right before the line of code when a *custom* event is being fired (as opposed to, say, using JQuery to fire a JS-standard event like simulating a key press), you want people to put in a docblock with @event in it, to explain what it is? OK, I can buy that.

Do we have any examples in core of these types of custom JavaScript events that we can use in the standards document, and if so, can someone write up a good sample docblock for one of them (including @fires in the function docblock, and an @event docblock where the event is actually fired off)?

attiks’s picture

Example from tabledrag.js

/**
 * Constructor for the tableDrag object. Provides table and field manipulation.
 *
 * @fires columnschange
 * @param table
 *   DOM object for the table to be made draggable.
 * @param tableSettings
 *   Settings for the table added via drupal_add_dragtable().
 */
Drupal.tableDrag = function (table, tableSettings) {
  /*
   * Trigger an event to allow other scripts to react to this display change.
   * @event columnschange
   */
  $('table.tabledrag-processed').trigger('columnschange', 'hide');
jhodgdon’s picture

Thanks for finding that! Below is yet another standards proposal... what do you think of this proposed standard for how to document events? I think it is consistent with how we document other types of things.

---
JavaScript code should be documented with documentation headers that are very similar to the PHP documentation headers described in http://drupal.org/node/1354 . Follow the standards described there, with the following changes:

  • All JavaScript items (methods, object constructors and properties, functions, variables, etc.) need to have documentation headers, or they will not be recognized at all by the parser (unlike the API module, which picks up all PHP items whether or not they have documentation headers).
  • Not all of the @tags we use for PHP are supported. Of the tags mentioned on http://drupal.org/node/1354, only use @file, @param, @return, @see, @link/@endlink, @code/@endcode, and @throws.
  • To indicate the type for a @param or @return tag, put the type in {} brackets: @param {TheType} paramName or @return {TheType}.
  • Additional tag: like @throws, which documents exceptions being thrown by a PHP or JavaScript function, use @fires to document events that are triggered by a JavaScript function. In addition, if the event is a custom event (as opposed to a standard event like a key press), add a documentation block immediately before the first line of code within a function that triggers the event, with an @event tag, to document the event itself (see sample below for details). Only include one @event block for each custom event, but use @fires in each function that triggers the custom event.
  • Some additional notation is required in many cases to help JSDoc figure out what type of item is being documented. Add tags to the bottom of the documentation block, as follows:
    • Use @lends Drupal before the start of a JQuery closure to indicate that everything within belongs to the Drupal namespace.
    • Use @constructor to indicate that a function is intended to be a class constructor. Immediately after the @constructor line (at the bottom of the documentation block), add a line starting with @classdesc to describe the purpose of the class that is being constructed by this constructor.
    • Use @namespace to indicate that an object is intended as a namespace.
    • You do not need to use @function though - JSDoc will assume anything declared as a function is a regular function or method, unless one of the tags above overrides this determination.

Here's a sample:

/**
 * @file JavaScript for draggable tables.
 */

/**
 * @lends Drupal
 */
(function ($) {
/**
 * Attaches the table drag behavior to tables.
 *
 * @namespace
 */
Drupal.behaviors.tableDrag = {
  /**
   * Attaches the behavior.
   *
   * @param context
   *    Something describing the context parameter.
   * @param settings
   *    Something describing the settings parameter.
   */
  attach: function (context, settings) {
       ...
  }
};

/**
 * Returns the value of foo for the current widget.
 *
 * Description of this ordinary function in the Drupal namespace goes here.
 *
 * @return
 *   The value of foo in the current widget.
 */
Drupal.getCurrentFoo = function () {
...
}

/**
 * Constructs a table drag object.
 *
 * @param table
 *   DOM object for the table to be made draggable.
 * @param tableSettings
 *   Settings for the table.
 *
 * @constructor
 * @classdesc Provides the ability to drag to manipulate a table and its fields.
 */
Drupal.tableDrag = function (table, tableSettings) {
  
  /**
   * Hides the columns containing weight and parent form elements.
   *
   * @fires columnschange
   * @see Drupal.tableDrag.showColumns
   */
  Drupal.tableDrag.prototype.hideColumns = function() {
    ...
    /**
     * Indicates that columns have changed in a table.
     *
     * @param type
     *   Type of change: 'show' or 'hide'.
     *
     * @event columnschange
     */
    $('table.tabledrag-processed').trigger('columnschange', 'hide');
    ...
  }
}

})(jQuery);

----

nod_’s picture

I've contacted micmath from JSDoc for a couple of questions, I'll reply about the standards once I get an answer from him :)

jhodgdon’s picture

What are your concerns nod_?

nod_’s picture

All right, I've exchanged a few mails with Michael Mathews who is taking care of JSDoc and on top of being really nice he had very interesting hindsights.

Aliases: There are preferred terms to use when aliases exists, on the usejsdoc.org, it's the first ones on the line. We'll use @return instead of @returns to match PHP, other than that it's looks good to me.

An hindsight from Michael is that @lends should be avoided and that we shouldn't rely too much on JSDoc for static analysis. As soon as the parser is confused we should be explicitly declaring a @name and not try to work around with another tag. His experience is that it works very well and avoid problems later on. (JSDoc is more than 10 years old, I'm happy to trust his judgment).

An example:

/**
 * Describe me.
 * @namespace Drupal
 */
var Drupal = {};
 
(function (Drupal) {
    /**
     * Describe me.
     * @constructor Drupal.TableDrag
     * @param {int} [columnCount=0] - The number of columns.
     */
    var TableDrag = function (columnCount) {
        /**
         * Describe me.
         * @member {int} Drupal.TableDrag#columnCount
         */
        this.columnCount = columnCount || 0;
    };
 
    /**
     * Describe me.
     * @method Drupal.TableDrag#showColumns
     */
    TableDrag.prototype.showColumns = function () {};
 
    Drupal.TableDrag = TableDrag;
}(Drupal));

I know we're not currently doing that but our code is very likely to change for this kind of construct (helps debugging/profiling).

Taking our code like it is today:

/**
 * Describe me.
 * @namespace
 */
var Drupal = {};
 
(function () {
    /**
     * Describe me.
     * @constructor
     * @param {int} [columnCount=0] - The number of columns.
     */
    Drupal.TableDrag = function (columnCount) {
        /**
         * Describe me.
         */
        this.columnCount = columnCount || 0;
    };
 
    /**
     * Describe me.
     */
    Drupal.TableDrag.prototype.showColumns = function () {};
}());

Updated commented code, the following produce a nice and helpful output from jsdoc (links between things and all):

/**
 * @file JavaScript for draggable tables.
 */

/**
 * @global
 * @namespace
 */
var Drupal = {};

/**
 * @namespace
 */
Drupal.behaviors = {};

(function ($) {
/**
 * Attaches the table drag behavior to tables.
 * @type {Object}
 *
 * @property {Function} attach
 *   My attach description
 * @property {Function} detach
 *   My detach description
 */
Drupal.behaviors.tableDrag = {
  // This should be documented in a file like drupal.api.js not for every behavior
  attach: function (context, settings) {
  }
};

/**
 * Returns the value of foo for the current widget.
 *
 * Description of this ordinary function in the Drupal namespace goes here.
 *
 * @return
 *   The value of foo in the current widget.
 */
Drupal.getCurrentFoo = function () {
};

/**
 * Constructs a table drag object.
 *
 * @param {HTMLTableElement} table
 *   DOM object for the table to be made draggable.
 * @param {Object} tableSettings
 *   Settings for the table.
 *
 * @constructor
 * @classdesc Provides the ability to drag to manipulate a table and its fields.
 */
Drupal.TableDrag = function (table, tableSettings) {
};

/**
 * Indicates that columns have changed in a table.
 *
 * @param {String} type
 *   Type of change: 'show' or 'hide'.
 * 
 * @event Drupal#columnschange
 */

/**
 * Hides the columns containing weight and parent form elements.
 *
 * @fires Drupal#columnschange
 * @see Drupal.TableDrag#showColumns
 */
Drupal.TableDrag.prototype.hideColumns = function() {
  $('table.tabledrag-processed').trigger('columnschange', 'hide');
};

/**
 * Shows the columns containing weight and parent form elements.
 *
 * @fires Drupal#columnschange
 * @see Drupal.TableDrag#hideColumns
 */
Drupal.TableDrag.prototype.showColumns = function() {
  $('table.tabledrag-processed').trigger('columnschange', 'hide');
};

}(jQuery));

What Drupal.behaviors expects should be documented somewhere else and liked to with @see

jhodgdon’s picture

nod_: I'm confused... Which one of those three code samples are you advocating we use? And have you verified (with the Drupal and Drupal.behaviors namespaces ***in a separate file, as they would be in real life*** that the one you are advocating actually works with JSDoc? In my tests, I needed the @lends Drupal line in order to get it to work with drupal.js having the actual declarations of the Drupal global variable.

Comparing the 3rd sample:
- I see that you left out the @namespace tag on Drupal.behaviors.tableDrag -- does JSDoc recognize this as a namespace without that tag?
- If the attach is documented elsewhere, we still need a documentation header of some sort to point to that documentation.
- Where did the @property detach come from? There is no detach defined that I can see?
- You prefer to have the @event block out in the middle of nowhere, instead of near where the event is thrown (which is what was shown in the JSDoc examples pointed to originally to illustrate @event)? If so, it should probably be in this mythical .api.js file?
- Why is the event Drupal#columnschange rather than just columnschange or something with tableDrag in the name? It's within the Drupal.tableDrag object...

nod_’s picture

The 3rd sample is what we should be using, the first one is a example of how we should be using @name when we need to. The second one is just like the first but with the javascript written in a JSDoc-friendly way.

Run the third piece of code through jsdoc, that should make a few things clearer.

1) Drupal.behaviors.tableDrag isn't a namespace, it's a Drupal-specific object that is always going to have the same structure. That's why I'm using @property to declare them to JSDoc. Drupal.behaviors is the namespace that interest us (the output of jsdoc is more useful that way).

2) yes, the actual docblock will be in mythical.api.js :p and a @see Drupal.behaviors can be added to the Drupal.behavior.tableDrag docblock to make a link to it.

3) My mistake, forgot to put it in the object.

4) In the tabledrag case the code to fire this event is called twice, So instead of choosing to document one and not the other I'm just documenting that somewhere close to the constructor.

5) Well that's kind of JSDoc thing, by putting Drupal#columnschange when you go to the Drupal.html doc page you'll see this event show up. Otherwise this event would be in global.html. And well, it is a Drupal-specific event so why not put that in the Drupal namespace.

jhodgdon’s picture

RE comment #57

0) Running through JSDoc - agreed, it seems to work without @lends now. Hm. Not sure what changed...

1) OK.

2) What would we call this mythical attach function that we are documenting in the api file? I mean, what name would it have? In order for this idea to work, everything we document needs to have a specific name (like what we do for PHP hooks -- we define a "function" called hook_whatever() for purposed of documentation, in the *.api.php files).

4) I disagree on this one. If we document things apart from where they are defined, the documentation does not tend to get maintained. We should just pick one place to document, and add a note like:

  // This event is documented in Drupal.tableDrag.hideColumns
  $('table.tabledrag-processed').trigger('columnschange', 'hide');

on the other one.

5) This Drupal#eventname syntax is probably not going to work well for us in the API module (the plan here is to use the JSDoc module to parse the JS code and documentation, and then to read it in and display it in the API module). The reason it works in pure JSDoc is that # is used in HTML to get to an anchor on the page, but we won't be doing the same thing in the API module. Also, the @see Drupal.className#methodName syntax is not going to work -- the API module will need them to be referred to as Drupal.className.methodName (just how you would invoke them).

So... I think if an event does not have a namespace prefix on its name, it shouldn't have a namespace in the documentation. We need to just refer to things by their *actual* names, not make up qualifiers that don't really exist. We'll get things grouped properly in the API module anyway.

nod_’s picture

4) sure, works for me.

So you won't be using the jsdoc parser and output in the api module to build the doc? Is that going to be a PHP parser? Check out the output from jsdoc -t templates/haruki -d console jsfile.js , no # in the JSON.

Drupal.className.methodName isn't correct, it's Drupal.className.prototype.methodName but that notation makes the .prototype appear and it's not actually useful to display that, It's better presented in the html jsdoc output. And technically that is not how you would invoke them, they would be invoked from the new object, not from the prototype.

The JS object model has nothing in common with PHP there has to be a few tweaks to have a proper documentation.

(edit) 2) Actually I think that would be well documented in the docblock with a @namespace (in drupal.js) with @example tags. There wouldn't be a good made-up name for it.

jhodgdon’s picture

Based on this, here is the latest modified proposal:

---
JavaScript code should be documented with documentation headers that are very similar to the PHP documentation headers described in http://drupal.org/node/1354, with modifications due to using the JSDoc3 parser as the first step in parsing the code and documentation. We generally follow the PHP standards as much as possible, with the following changes:

  • All JavaScript items (methods, object constructors and properties, functions, variables, etc.) need to have documentation headers, or they will not be recognized at all by the parser (unlike the API module, which picks up all PHP items whether or not they have documentation headers).
  • Not all of the @tags we use for PHP are supported. Of the tags mentioned on http://drupal.org/node/1354, only use @file, @param, @return, @see, @link/@endlink, @code/@endcode, and @throws.
  • To indicate the type for a @param or @return tag, put the type in {} brackets: @param {TheType} paramName or @return {TheType}. [We need to make standards for the types to use, like we have for PHP types!!!]
  • Additional tag: like @throws, which documents exceptions being thrown by a PHP or JavaScript function, use @fires to document events that are triggered by a JavaScript function. In addition, if the event is a custom event (as opposed to a standard event like a key press), add a documentation block immediately before the first line of code within a function that triggers the event, with an @event tag, to document the event itself (see sample below for details). Only include one @event block for each custom event, but use @fires in each function that triggers the custom event.
  • Additional tag: when documenting an object that is not being used as a namespace or class, use @property {type} name tags to document its properties (these work like
    @param for function parameters).</li>
    <li>Some additional notation is required in many cases to help JSDoc figure out what type of item is being documented. Add tags to the bottom of the documentation block, as follows:
      <ul>
      <li>Use <code>@lends Drupal

    before the start of a {} to indicate that everything within belongs to the Drupal namespace. This is only needed if the items within are called just name rather than the full Drupal.name

  • Use @constructor to indicate that a function is intended to be a class constructor. Immediately after the @constructor line (at the bottom of the documentation block), add a line starting with @classdesc to describe the purpose of the class that is being constructed by this constructor.
  • Use @namespace to indicate that an object is intended as a namespace.
  • You do not need to use @function in most cases - JSDoc will assume anything declared as a function is a regular function or method, unless one of the tags above overrides this determination.

Here's a sample:

// In the drupal.js file:
/**
 * Holds JavaScript settings and other information for Drupal.
 *
 * @namespace
 */
var Drupal = Drupal || /** @lends Drupal */ {
   // ...

 /**
  * Holds behaviors for Drupal.
  * @namespace
  */
 'behaviors': {},

  // ...
}

// In a file such as tabledrag.js:

/**
 * @file JavaScript for draggable tables.
 */

(function ($) {
/**
 * Attaches the table drag behavior to tables.
 *
 * @property {function} attach
 *   Description of the attach function goes here.
 */
Drupal.behaviors.tableDrag = {
  attach: function (context, settings) {
    // ...
  }
};

/**
 * Returns the value of foo for the current widget.
 *
 * Description of this ordinary function in the Drupal namespace goes here.
 *
 * @return
 *   The value of foo in the current widget.
 */
Drupal.getCurrentFoo = function () {
  // ...
};

/**
 * Constructs a table drag object.
 *
 * @param {HTMLTableElement} table
 *   DOM object for the table to be made draggable.
 * @param {object} tableSettings
 *   Settings for the table.
 *
 * @constructor
 * @classdesc Provides the ability to drag to manipulate a table and its fields.
 */
Drupal.tableDrag = function (table, tableSettings) {
  // ...
}

/**
 * Hides the columns containing weight and parent form elements.
 *
 * @fires columnschange
 * @see Drupal.tableDrag.showColumns
 */
Drupal.tableDrag.prototype.hideColumns = function() {
  // ...
  /**
   * Indicates that columns have changed in a table.
   *
   * @param type
   *   Type of change: 'show' or 'hide'.
   *
   * @event columnschange
   */
  $('table.tableDrag-processed').trigger('columnschange', 'hide');
  // ...
};

/**
 * Shows the columns containing weight and parent form elements.
 *
 * @fires columnschange
 * @see Drupal.tableDrag.hideColumns
 */
Drupal.tableDrag.prototype.showColumns = function() {
  // This event is documented in Drupal.tableDrag.hideColumns
  $('table.tabledrag-processed').trigger('columnschange', 'hide');
};

}(jQuery));

---

jhodgdon’s picture

RE #59 --

- We aren't going to be using the haruki formatter. It does not have enough information. Probably we'll be using the -X (dump) output, which has all the information included. But that is best left for the issue in the API module and does not impact the standards that we choose for documentation really.

- The JSDoc parser takes Drupal.tableDrag.prototype.functionName and gives it to me as Drupal.tableDrag.functionName, so I think we need to use that in @see links. I realize it is *defined* as .prototype, but for purposes of documentation, it is cleaner to omit that, I think.

- RE item (2) - I don't get it. Please provide a sample so I can understand your proposal.

nod_’s picture

My understanding was that we're using JSDoc to avoid drupalism and rely on a tool that is already working. Not using the # break links when the doc is generated by jsdoc, that is not helpful. If our documentation is only possible to generate with the API module we're losing all the benefits of using a third party tool.

See here for what the # is about: http://code.google.com/p/jsdoc-toolkit/wiki/NamePaths

But we're not very effective here, are we deciding on a doc standard or are we documenting drupal.js? This drupal.js file has some unique requirement that won't be used in contrib. in contrib you'll see things like tabledrag. We shouldn't be spending that much time worring about it and focus on events, libraries, constructor and this kind of things. do you want me to send a properly commented drupal.js and/or tableselect.js (tabledrag is way to big) to see how JSDoc should be used? would that help?

For the Objects available, it's basically all the JS primitives (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/ under "General-purpose constructors") + DOM constructors (HTMLElement, HTMLTableElement, etc. https://developer.mozilla.org/en/Gecko_DOM_Reference) + any user-defined constructor (like TableDrag). They all starts with uppercase except null, undefined, false, true (and that's it I think).

Putting /** @lends */ in the middle of an expression is not good. Using @name is much easier and has no chance of breaking the code.

The following provides a satisfactory output from JSDoc:

/**
 * Holds JavaScript settings and other information for Drupal.
 *
 * @global
 */
var Drupal = Drupal || {

  /**
    Holds behaviors for Drupal. (yes I didn't put the "*" before, don't have my helpful editor available).
    
    @namespace
    @name Drupal.behaviors
    
    @example
    Drupal.behaviors.myBehavior = {
      // This is run during page load and on AJAX calls.
      attach: function (context, settings) { },
      // This is run before an AJAX call happens.
      detach: function (context, settings, trigger) { }
    };
   */
  "behaviors": {}
};

 
 
// In a file such as tabledrag.js:

/**
 * @file JavaScript for draggable tables.
 */

(function ($) {
/**
 * Attaches the table drag behavior to tables.
 *
 * @property {Function} attach
 *   Description of the attach function goes here.
 */
Drupal.behaviors.tableDrag = {
  attach: function (context, settings) {}
};

/**
 * Returns the value of foo for the current widget.
 *
 * Description of this ordinary function in the Drupal namespace goes here.
 *
 * @return
 *   The value of foo in the current widget.
 */
Drupal.getCurrentFoo = function () {
  // ...
};

/**
 * Constructs a table drag object.
 *
 * @param {HTMLTableElement} table
 *   DOM object for the table to be made draggable.
 * @param {Object} tableSettings
 *   Settings for the table.
 *
 * @constructor
 * @classdesc Provides the ability to drag to manipulate a table and its fields.
 */
Drupal.tableDrag = function (table, tableSettings) {
  // ...
}

/**
 * Hides the columns containing weight and parent form elements.
 *
 * @fires columnschange
 * @see Drupal.tableDrag#showColumns
 */
Drupal.tableDrag.prototype.hideColumns = function() {
  // ...
  /**
   * Indicates that columns have changed in a table.
   *
   * @param {String} type
   *   Type of change: 'show' or 'hide'.
   *
   * @event columnschange
   */
  $('table.tableDrag-processed').trigger('columnschange', 'hide');
  // ...
};

/**
 * Shows the columns containing weight and parent form elements.
 *
 * @fires columnschange
 * @see Drupal.tableDrag#hideColumns
 */
Drupal.tableDrag.prototype.showColumns = function() {
  // This event is documented in Drupal.tableDrag.hideColumns
  $('table.tabledrag-processed').trigger('columnschange', 'hide');
};

}(jQuery));

Drupal.behaviors will be gone by D8 one way or another, so we shouldn't scratch our heads too much about it. Also we can't document D7 since that will add a massive amount of filesize that is not acceptable on frontend without previous minification.

I'm putting this thing in question if we can't get a useful output from jsdoc with out drupal js files.

jhodgdon’s picture

Thanks for the information on data types... I also looked in my JavaScript book and found the names of the primitive JS types.

Regarding the Drupal.behaviors.*.attach function, we need a place where we can document the @param/@return values for this type of function. Otherwise, we need to document each one separately. (Again, this is similar to what we do for hooks in PHP code -- we have the @param/@return on the hook_ function docs in the api.php file, and we don't repeat it on the implementations.)

Regarding philosophy... nod_ -- it appears that our aims may differ here. My aims:

a) Find a JS documentation parser that will parse comments as close to our PHP standards as possible, and produce output that the API module can read. [It looks like JSDoc is the best candidate for that, in -X (debug dump) mode.]

b) Take that output and integrate it into the API module, so that we can display JavaScript code on api.drupal.org in a way very similar to how we display PHP code now, make links between the PHP and JavaScript code, have automatic links made to function names and classes in the JavaScript documentation like we do now for PHP, etc. [That has yet to be done, of course.]

c) Adopt JavaScript documentation standards with the following characteristics:
- Readable by the JS documentation parser we have adopted.
- Contains enough information to support linking and display in the API module.
- Readable by people looking at the JS files directly.
- Makes sense within the JavaScript language.
- Maintainable by Drupal developers.
- As close to the PHP standards we already have as possible (so people don't have to learn two very different standards).
- Similar to other documentation standards across the software industry (doxygen, JavaDoc, etc.)
- Able to be clearly articulated in a standards document and easily illustrated with a short example, without lots of exceptions and special cases.

I personally do not care at all whether we can use pure JSDoc to make great output from our JavaScript files -- we also can't use pure doxygen to make great output from our PHP files. In both cases, there are customizations that we've made (or will make) in the API module that are Drupal-centric and that help us create a truly useful api.drupal.org site, well beyond what we could do with the underlying doxygen/JSDoc technology.

Anyway... I think that my most recent proposal in #60 satisfies my goals, with the slight change to using @name vs. @lends that you suggested in #61 (which I agree is cleaner). If you have other examples that you think we need to add to the sample code, which illustrate cases that are not covered by the sample code (whether needed for core or contrib), then yes we should definitely add them to the standard. I don't think we need/want to have a fully-documented sample file in the standards document (eventually we'll need to make patches for all the JS files in core, but not for the standard, which is what we're working on now).

So... are there any other opinions about this proposal? Which is hereby amended (once again) to read:

---
JavaScript code should be documented with documentation headers that are very similar to the PHP documentation headers described in http://drupal.org/node/1354, with modifications due to using the JSDoc3 parser as the first step in parsing the code and documentation. We generally follow the PHP standards as much as possible, with the following changes:

  • All JavaScript items (methods, object constructors and properties, functions, variables, etc.) need to have documentation headers, or they will not be recognized at all by the parser (unlike the API module, which picks up all PHP items whether or not they have documentation headers).
  • Not all of the @tags we use for PHP are supported. Of the tags mentioned on http://drupal.org/node/1354, only use @file, @param, @return, @see, @link/@endlink, @code/@endcode, and @throws.
  • To indicate the data type for a @param or @return tag, put the data type in {} brackets: @param {TheType} paramName or @return {TheType}. For non-object data, use number, string, bool, null, undefined, object, array, function. For objects of a particular class, use the class (constructor) name; this could be a built-in JavaScript class (Date, RegExp), a DOM element (Document, Checkbox), a Drupal-specific class (Drupal.AJAX), etc.
  • Additional tag: like @throws, which documents exceptions being thrown by a PHP or JavaScript function, use @fires to document events that are triggered by a JavaScript function. In addition, if the event is a custom event (as opposed to a standard event like a key press), add a documentation block immediately before the first line of code within a function that triggers the event, with an @event tag, to document the event itself (see sample below for details). Only include one @event block for each custom event, but use @fires in each function that triggers the custom event.
  • Additional tag: when documenting an object that is not being used as a namespace or class, use @property {type} name tags to document its properties (these work like @param for function parameters).
  • Some additional notation is required in many cases to help JSDoc figure out what type of item is being documented. Add tags to the bottom of the documentation block, as follows:
    • Use @name (name) near the bottom of a documentation block to tell JSDoc the name of what is being documented, if it is not the same as the name in the code (usually because it is a property name like foo rather than including the class name like Bar.foo).
    • Use @constructor to indicate that a function is intended to be a class constructor. Immediately after the @constructor line (at the bottom of the documentation block), add a line starting with @classdesc to describe the purpose of the class that is being constructed by this constructor.
    • Use @namespace to indicate that an object is intended as a namespace.
    • You do not need to use @function in most cases - JSDoc will assume anything declared as a function is a regular function or method, unless one of the tags above overrides this determination.

Here's a sample:

// From the drupal.js file:
/**
 * Holds JavaScript settings and other information for Drupal.
 *
 * @namespace
 */
var Drupal = Drupal || {
   // ...

  /**
   * Holds behaviors for Drupal.
   *
   * @namespace
   * @name Drupal.behaviors
   */
  'behaviors': {},

  // ...
}

// In a file such as tabledrag.js:

/**
 * @file JavaScript for draggable tables.
 */

(function ($) {
/**
 * Attaches the table drag behavior to tables.
 *
 * @property {function} attach
 *   Specific description of this attach function goes here.
 */
Drupal.behaviors.tableDrag = {
  attach: function (context, settings) {
    // ...
  }
};

/**
 * Returns the value of foo for the current widget.
 *
 * Description of this ordinary function in the Drupal namespace goes here.
 *
 * @return
 *   The value of foo in the current widget.
 */
Drupal.getCurrentFoo = function () {
  // ...
};

/**
 * Constructs a table drag object.
 *
 * @param {HTMLTableElement} table
 *   DOM object for the table to be made draggable.
 * @param {object} tableSettings
 *   Settings for the table.
 *
 * @constructor
 * @classdesc Provides the ability to drag to manipulate a table and its fields.
 */
Drupal.tableDrag = function (table, tableSettings) {
  // ...
}

/**
 * Hides the columns containing weight and parent form elements.
 *
 * @fires columnschange
 * @see Drupal.tableDrag.showColumns
 */
Drupal.tableDrag.prototype.hideColumns = function() {
  // ...
  /**
   * Indicates that columns have changed in a table.
   *
   * @param type
   *   Type of change: 'show' or 'hide'.
   *
   * @event columnschange
   */
  $('table.tableDrag-processed').trigger('columnschange', 'hide');
  // ...
};

/**
 * Shows the columns containing weight and parent form elements.
 *
 * @fires columnschange
 * @see Drupal.tableDrag.hideColumns
 */
Drupal.tableDrag.prototype.showColumns = function() {
  // This event is documented in Drupal.tableDrag.hideColumns
  $('table.tabledrag-processed').trigger('columnschange', 'hide');
};

}(jQuery));

---

nod_’s picture

I disagree with the fact our JS documentation will not be useful when ran through JSDoc, this will bite us. It means we will not take advantage of future evolutions and should we run into problems support will be more difficult. We will loose time in the long run. In this case a "dumber" tool like YUIDoc is better suited. The only issue raised against YUIDoc is that we'd have to declare every method name in the docblock. Since we'll be using @name for JSDoc to acheive the same thing I don't think that's a major issue. Function names hardly changes in JS patches and most of our JS will be rewritten for D8, it will be easy to take into account new doc standards while keeping everything documented.

I will wait for feedback from another core contributor or someone from the API module for their opinions. I still have a couple of details I'd like changed in the current proposal.

ksenzee’s picture

If we can easily structure our code so we get useful output from JSDoc, then that seems fine, but I don't honestly see the benefit. It's not like this is reusable library code that anyone outside of Drupal will ever even look at. I think getting it into API module is enough of a goal in itself.

jhodgdon’s picture

RE #64: *I* am the current maintainer of the API module, so you have that opinion already.

nod_’s picture

All right then, thanks for providing feedback. I have some from Michael Mathews, the JSDoc maintainer, to share:

Overall goal of similar PHP-JS documentation

Haruki was actually an experiment, implemented by a team at the company I work, who tried to get one standard mutual documentation format for both PHP and JavaScript. It was even used in production for several months.

The result of that experiment was that actually PHP and JS are too different to try to force them both into one single output. You can do it, but you lose too much to make it worthwhile. (NaturalDocs is a tool that you might look at if this is your goal.) Therefore the haruki template was mostly abandoned for the last year. I only leave it in there in case someone wants to make some use of the considerable amount of work that went in to it to base their own JSON-based template on. (This might be an option for you in fact.)

./jsdoc -X

Using the debugging output is a bit risky since it's not guaranteed to be the same from release to release.

#

The "#" is very much a historical artefact, being in use since the very first version of JSDoc, and has never been a problem before. On the other hand "#" is just an artefact, and certainly is less valid than "prototype" since the latter is part of ECMAScript itself!

Overall Drupal JS documentation goal

[…] from reading that discussion it looks to me like you are headed down a path that will result in a bespoke custom-built Drupal documentation tool. I know a tiny bit about how much work it requires to get that sort of thing right, so I wish you a great deal of luck should you take that path!

This is his take on the situation, I'm only quoting to provide some more input in an issue with too few people involved for it's scope.

Now here there is an actual problems in the current proposal:
@see Drupal.tableDrag.showColumns is not correct. You will not be able to call this function like that. It should be either @see Drupal.tableDrag#showColumns or @see Drupal.tableDrag.prototype.showColumns. I'm one of the people who will end up writing a lot of JS code and doc, I'd rather the shorter version. And since people using JSDoc are familiar with it won't look strange to them (it's been used for 10 years after all).

There are still references to classes:
For objects of a particular class, use the class (constructor) name; this could be a built-in JavaScript class (Date, RegExp), a DOM element (Document, Checkbox), a Drupal-specific class (Drupal.AJAX), etc.

changed to
For objects of a particular type, use the constructor name; this could be a built-in JavaScript constructor (Date, RegExp), a DOM element (HTMLDocument, HTMLInputElement), a Drupal-specific constructor: Drupal.ajax (sic), etc.

And also:
Use @constructor to indicate that a function is intended to be a class constructor. Immediately after the @constructor line (at the bottom of the documentation block), add a line starting with @classdesc to describe the purpose of the class that is being constructed by this constructor.
To
Use @constructor to indicate that a function is intended to be an object constructor. Immediately after the @constructor line (at the bottom of the documentation block). If the object contstructed needs a different description than the constructor, add a line starting with @classdesc to describe the purpose of the object that is being created by this constructor.

A minor thing:
I'd rather have String, Number, etc. instead of string, number in primitive types, but I can live with that.

Now since in this standard definition issue we're mentioning the actual implementation, the way to go is extend/tweak the haruki publish.js template to output a JSON tree that will be suitable to be consumed by the api module. This will remove the dependency on the raw output of jsdoc. He just confirmed to me that "the data passed to publish.js will never change in a backwards incompatible way between versions.".

nod_’s picture

One more use case I overlooked and that we are currently using in core JS supporting the use of # (another quote)

By the way, replacing "#" with "prototype" at least has some justification in ECMAScript. Replacing "#" with "." is just stating wrong information; Foo.bar quite simply is not the same thing as Foo.prototype.bar.

And further, consider...

/** @constructor */
function Foo() {
    this.bar = 1;
}

In this case your user cannot access bar via Foo.bar nor Foo.prototype.bar. I suppose you could describe that as (new Foo()).bar but that's not quite as easy to write as Foo#bar. The general point is the # means something specific, and is known to people who use JSDoc. I would most definitely not recommend that anyone simply replace it with "." unless there was some extremely well thought out reason to do so.

jhodgdon’s picture

Status: Needs review » Postponed

Regarding -X or haruki -- we need *something* to use in the API module. If we can't use -X because it is not consistent, and Haruki is an "experiment" (which, as I've said before doesn't give us everything we need anyway), then our alternatives are either to write our own template system (which I do *not* want to do), or just give up on the whole idea. Or is there another solution I am not seeing?

Regarding classes/methods... of course, most class methods in PHP also cannot be accessed via ClassName.MethodName or ClassName::methodName even (unless they happen to be static methods). But it is still a useful shorthand to display them as ClassName::methodName, and at least my JavaScript book (O'Reilly's JavaScript: The Essentials) uses this notation for the built-in DOM and core JavaScript classes. They don't use ClassName#methodName and I have never seen this anywhere...

Anyway, I have given up. I obviously cannot satisfy nod_ and no one else is weighing in, so unless someone else wants to write some standards for how we should document and display JavaScript, I will revert to the status quo on api.drupal.org, and we won't display anything. Sorry.

This issue is hereby postponed indefinitely until we can agree upon some standards that will work for developers, the API module, etc. Right now I don't see any way that can happen.

nod_’s picture

write our own template system output (which I do *not* want to do)

I'm happy to do it if that's what it takes. Just tell me the structure of the json you want to work with. It'll be much easier than implementing our own thing on the PHP side.

uses this notation for the built-in DOM and core JavaScript classes.

For all DOM-related things that's normal and check again about core JS types and objects. I'm pretty sure you won't see Date.getTime() anywhere (or the book is actually bad). myDate.getTime() is much more likely.

They don't use ClassName#methodName and I have never seen this anywhere

That's fine, let's just use .prototype. instead, it's explicit and valid, that is not a major problem.

I obviously cannot satisfy nod_

Sure you can, just let us (me) use the full jsdoc tool and not an incompatible subset of it that'll lack the necessary constructs to document all the code we can come up with in core and contrib.

[…] we can agree upon some standards that will work for developers, the API module, etc. Right now I don't see any way that can happen.

Now I'm happy to use JSDoc, I used to prefer YUIDoc. Let me know what kind of json/xml/PHP/anything you want to us and i'll write the publish.js script that'll make it work.

jhodgdon’s picture

You are incorrect about the Date.getMonth() and other methods in JavaScript: The Definitive Guide. It is *convenient* when making documentation to list methods that way. It is not an implication that they can be *used* that way at all.

Regarding your willingness to make JSDoc or other add-ons -- the API module can use any kind of JSON or XML format that is stable, maintained by the JSDoc folks, and has all the information we would need, but the API module maintainers do not want to take on maintenance of JSDoc code (even if you write the initial version). So, I don't think JSDoc is viable at this time.

Until we find a different parser to use, we should just postpone this discussion.

nod_’s picture

FileSize
398 bytes
8.11 KB
1.84 KB

Last try from me on JSDoc.

So the data structure that is passed to publish.js script is guaranteed to be stable (see previous posts), so we can use it reliably. Dumping the stable dataset is easy. Because we're dumping everything, we end up with a list of everything picked up by JSDoc parser, including undocumented functions.

I attached a sample js file with 1 undocumented function, the publish.js that generates it, and the json output. The publish file should be added to templates/drupal/publish.js:

publish = function (data, opts) {
  function filter(key, value) {
    // 'node' key don't properly export as JSON, remove them.
    if (key === 'node' && typeof value === 'object') { return; }
    // Normal behavior.
    return value;
  }
  var filteredData = JSON.stringify(data.get(), filter, '  ');
  console.log(filteredData);
};

The json output comes from jsdoc -t templates/drupal jsdoc.js. Since data will not change, this piece of code will not change either. This will output a flat list of everything picked up by JSDoc.

It needs to have a filter function but i'm pretty sure this is a bug in console.log and/or the object making this crash (object coming straight from rhino it seems) and not a JSDoc thing per say. If this is confirmed and fixed upstream the publish.js code will amount to: publish = function (data, opts) { console.log(data.stringify()); };
That's it.

(edit) reformat.

attiks’s picture

Status: Postponed » Active

my 2 cents:

As far as I have test jsdoc looks like a great tool to generate the documentation and after re-reading this issue the only 2 'problems' are:

  1. Generating suitable output, but this is solved by @nod_ solutions from #72
  2. Deciding how we will list methods: Date.getTime() versus myDate.getTime(), but I think in the end it doesn't really matter how it's documented, as long as it is documented in a clear way. It's like @jhodgdon said in #69, for PHP the notation isn't 'correct' either.

If the maintainability of @nod_'s publish.js is a problem I'm more than willing to help maintain it.

jhodgdon’s picture

FileSize
166.79 KB

I have some concerns about this approach:
a) We would need to maintain this publish.js file presumably within the API project. However, JSDoc is really lame about templates -- you cannot apparently have the templates living anywhere except in the JSDoc directory (you're not allowed to provide a path to the template directory). Which means that anyone who wanted to use this publish.js would need to take the file from the API module download and copy it into their JSDoc download. That kind of installation step is subject to problems.

b) The publish.js that is suggested in #72 only outputs to the "console" (i.e., stdout). But if you redirect this to a file, you get in addition a message at the top saying

Running Normal

which of course is not proper JSON and would need to be removed. So, it probably needs to get more complex so it can output somewhere else, meaning more maintenance.

c) The publish.js suggested here does not match the syntax of the ones provided with the JSDoc package. They all look like:

(function() {
  publish = function(...) { ... }
})();

Shouldn't this version do this too?

d) I actually am not sure this output (attached) will even work for us on our real JS files. Sure, it works fine for simple cases, but take a look at this output based on drupal.js, ajax.js, autocomplete.js, and tabledrag.js (with comments added). It's rather a mess... Anyway, it does produce pretty much the same output as -X (aside from whitespace and the fact that -X includes the "nodes", which are ignored in the suggested publish.js). I'm just not sure, looking at this closer, whether we can use it. Any thoughts?

attiks’s picture

a) see https://github.com/jsdoc3/jsdoc/pull/122
b) i think @nod_ just wanted to show how it can be solved, his solution is only a couple of lines.
c) can easily be fixed
d) see c

nod_’s picture

a) sent a pull this morning to fix that.

b) there is another issue (with a patch i think) to remove this "Running Normal" with a command line option. I'll get that going and send a patch if needed.

c) the closure is used because they are declaring variables and function they don't want leaking into the global scope. There is nothing of the sort for us so we don't need it.

d) "node" is a reference to a java object coming straight from rhino so this wouldn't have meaningful information for us. Also I don't think the dump output is valid json or valid anything for that matter so that'll be a pain to parse it (there is still the xml output though, don't know how good it is). Well the data isn't really meant to be used directly like that so it's kind of messy. There are intermediary files while building the default template, that might be more useful.

jhodgdon’s picture

RE d... OK on the nodes. All I'm saying is that -X gives the same exact output (aside from including the nodes, and whitespace) as the script here. Which is fine... except that looking in detail at the output from a more complicated case (see attachment in #74, which came from the publish.js, not from -X), I'm not sure how useful it is, or how I would know off-hand what I wanted to grab in the API module and what I don't want to grab. A lot of the entries in there seem to be completely useless to us.

One other thing noticed is that adding additional tags not known by JSDoc is not a good idea (like @code), so we'd have to remove that from our standards. And it just seems like the JSDoc output would be unusable if someone screwed up the documentation somehow -- it doesn't seem to be very robust.

So... I just don't see this working out very well in reality. It is fine for little test cases, but we're talking here about all of Drupal JS, and I think in the real world we are not going to get this to work well. Maybe I'm being pessimistic, but I haven't seen anything yet that makes me all that optimistic about getting this whole idea to work, or even coming to any sort of agreement on standards for coding, much less how (if?) it should be displayed on api.drupal.org.

nod_’s picture

I can point you to #25901-46: Parse/save/display JavaScript files which is an output from yuidoc and gives a friendlier data structure to work with. The only drawback raised against it was the need for explicitly naming all function. Small price to pay for not having to support a custom parser. It's also my role to enforce whatever doc standard we agree on.

(edit) I don't mind sending patch to the api module to help out. About the scope of what we should expose i'd go with everything that's documented. we really don't have that many things going on.

jhodgdon’s picture

Title: Create/adopt JavaScript docs standards compatible with JSDoc parser » Create/adopt JavaScript docs standards compatible with a JS documentation parser
Status: Active » Postponed

I have now evaluated both JSDOc and YUIdoc -- see summaries at
#25901-63: Parse/save/display JavaScript files
#25901-65: Parse/save/display JavaScript files

Unless someone has a better idea, I don't think we'll be displaying nice JavaScript documentation on api.drupal.org anytime soon using one of these parsers, so I don't think there is much point in adopting formal JavaScript standards to conform to either YUIDoc or JSDoc parsing.

So, for the moment, all we can really do is stick with what our current JS standards say, which is to use the PHP doc standards on http://drupal.org/node/1354. For now, that is our best option -- at least it would create human-readable documentation, and if we need to adapt it later for a hypothetical usable JS Parser that (as far as I can tell now) doesn't yet exist, we can do that then. Until then, let's just mark this (once again) postponed, and start at least adding some documentation headers with @param and @return on the functions... I'll update the summary.

jhodgdon’s picture

Issue summary: View changes

Update link to JSDoc toolkit

attiks’s picture

I read all comments again, most of it is handled, the thing that missing in my proof of concept is
- handling of prototype
- handling of @constructor (for each class I add a constructor)
- namespaces (since API doesn't support it) are now treated as classes

I'm using some test files so we can easily decide what has to be interpreted as what, see http://drupalapi.attiks.com/api/js-samples/files/7

jhodgdon’s picture

The API module will shortly be handling PHP namespaces -- I'm working on #1507476: Support namespaces in API module right now. However, I don't think they are at all the same concept as JS namespaces, so I don't think the JS handling of them will be the same. Really, all of the JS constructs need to be handled in a way that makes sense for JS. We won't be merging the JS docs things and the PHP docs things -- they just don't scale.

So let's make sure there is a standard for JS documentation that makes sense for JS, and that the JS parser can read and make sense of, rather than trying to match it up to PHP concepts.

Can we get a few sample JS files posted here, with patched documentation, and some idea of what the JS parser will do with them (what will be treated as a class, constructor, function, namespace, etc.), so that we can come to an agreement on JS docs standards and how the information should be displayed on api.d.o? Or is it still premature since the JSDoc parser current version still doesn't handle everything?

attiks’s picture

The test files I'm using are the ones from #25901-63: Parse/save/display JavaScript files and jsdoc finds everything AFAIK. I only changed namespace to classes so I got some output.

I'll try to find a good way to handle this separately from the php.

+1 on getting an agreement on how we want to document things, this will take more time then adapting jsdoc to our needs.

youngelpaso’s picture

This is a very interesting thread. Nice work by everyone involved and as a total outsider I appreciate all of the effort you guys have put it. I'm working at McGill University and we're testing out using JSDOC3 for our JS documentation. So far so good, but we're not really dealing with the same scale or modularity issues that you are here. Nonetheless I look forward to seeing how this all turns out and if our experience ends up being at all germane or useful to document here I will. Cheers

youngelpaso’s picture

Issue summary: View changes

update status

jhodgdon’s picture

Title: Create/adopt JavaScript docs standards compatible with a JS documentation parser » [policy, no patch] Create/adopt JavaScript docs standards compatible with a JS documentation parser
Priority: Normal » Major
Issue summary: View changes
Status: Postponed » Active

We need to un-postpone this and figure this out now.

There is a "major" issue that is postponed until this is figured out.
#2182153: [Meta] Document Drupal JavaScript using JSDoc

jhodgdon’s picture

A few thoughts on moving this forward:

a) If we adopt an established JS docs parser, we should be able to write a fairly short standards page that basically says:

See (link) for general guidelines on how to write JS doc comments.

And then have a section for the specific standards that apply to the Drupal project. For instance, the docs parser we adopt might allow you to have @param or @return without a description, but we might require that parameters and return values have descriptions as well as just data types (as we do in PHP). And we might require that certain types of things in JS are documented (files, functions, etc.). And that you indent two spaces for the description of an @param/@return. Etc.

And it has been helpful in the PHP docs standards page also to set out the order of the @tags.

b) We have held up this issue on the idea that the JS doc parser should provide output that we can integrate into the API module and hence display on api.drupal.org. But we should probably relax that. We should adopt a viable and industry-standard JS doc parser, and if it will generate its own JS documentation output, we can just put that at api.drupal.org/js or something like that. I just don't think we need to make it a requirement that the JS docs and the PHP docs be integrated, and it may be more trouble to maintain than it is worth.

c) Before we adopt a particular parser for JS, I'd like to see (1) some evidence that it is "industry standard" (2) some evidence that it is a well-supported open-source project and (3) the output that it makes -- either a way to integrate that into the API module or a stand-alone set of output -- based on our actual Core JS code for Drupal 7 and 8 (a representative sample with documentation headers added).

nod_’s picture

I'll address the other points later, just want to outline that we can't document drupal 7 javascript because we don't minify D7 core javascript files and comment overhead is too much on overall file size.

jhodgdon’s picture

Good point! Let's put that in the standards page then?

nod_’s picture

Created the doc page at https://drupal.org/node/2183405 copied #63 in to the doc page. Now I need to redact it properly. I also sent an email to the JSDoc user list asking for help/feedback on the current JSDoc patch.

jhodgdon’s picture

Let us know when the proposed standards page is ready for review. I think maybe saying to refer to node/1354 (the PHP standards) is not the best idea for that page -- it seems like PHP is too different from JS to be useful? I think starting from the JSDoc tag reference (via a link) and then explaining things like:
- Which tags we require to be used where
- Additions like "@param needs description" and formatting (line length, indentation, etc.)
- A representative documented code sample.

Regarding your question to the JSDoc list about a tag reference, they seem to have:
http://code.google.com/p/jsdoc-toolkit/wiki/TagReference
That isn't awful, in my opinion, assuming that it is all complete and correct. I don't really think we need to insist on a one-page reference -- that at least gives you a list of the available tags and you can click through to get more information.

And let us know the outcome is of your JSDoc email query... from that email message, it looks like JSDoc is not quite ready to deal with our code?

nod_’s picture

I checked in the all.json file, JSDoc can deal with it. All the information we want is available in there, it's the raw data, so JSDoc does pick everything up. So it's "only" a template problem, maybe someone else ran into this.

jhodgdon’s picture

Ah, that's interesting. Well I can see the possibility of us running the (currently hypothetical) Drupal JS docs site with a custom template that we maintain in a d.o git repo. That doesn't actually sound like a completely terrible idea; however it would probably be better if we could use their standard template. Are the maintainers of JSDoc open to patches?

jhodgdon’s picture

Project: Drupal core » Drupal Technical Working Group
Version: 8.0.x-dev »
Component: documentation » Code

Coding standards decisions are now supposed to be made by the TWG

nod_’s picture

Beside finalizing "Write a standards page for Drupal JS doc headers" I think the rest of the tasks in the issue summary have been addressed.

markcarver’s picture

FWIW (as a front-end developer), and after reading the back and forth between @nod_ and @jhodgdon, I have to agree with @nod_ here.

PHP and JS are two separate languages, granted similar in many regards, but nonetheless fundamentally entirely different.

Attempting to enforce our PHP documentation standards onto JS code is just not going to work. Period.

Just like it won't work for any potential future SASS documentation standards (re: auto-creating style-guides with KSS).

There's been some mentions about JSDoc not being "human-readable", I have to really disagree with that. When you're a front-ender and used to working with JS, it makes a hell of a lot more sense than the PHP doxygen stuff front-enders are forced to learn because of Drupal.

I'm not saying that the Doxygen stuff for PHP isn't needed or good, cause it is... but it's for PHP and it does work really well for that. Trying to re-invent the JSDoc wheel just because it doesn't work with api.d.o will get us in more trouble than it's worth.

A separate site would be far more beneficial (and preferable) than trying to merge it with api.d.o, maybe js.d.o? Then api.d.o can simply just link the JS files it finds to the js.d.o site and not not have to worry about parsing it at all.

attiks’s picture

#94 integration is possible, i build something like it 2 years ago, it uses jsdoc tot parse the comments and transforms it to what's used by the api site.

With this patch we can have both.

markcarver’s picture

Anything is "possible", that wasn't the point I was trying to make... please re-read.

jhodgdon’s picture

@markcarter: I think we have a viable JS docs standards page now, and I'm certainly not (at least today :) ) asking for us to use *exactly* the same syntax in PHP and JS. I agree that we should use the syntax of JSDoc for the JSDoc comments, and the syntax we have now for the PHP docs, and I agree that we should not try to change JSDoc's syntax.

But I think as far as standards go, like:
- Everything needs a doc block (files, functions, classes, ...)
- Everything needs a description (overall doc blocks, params, returns, etc.)
we should try to have the same or similar standards in JS and PHP. And if there is flexibility in the formatting for JSDoc, like

* @param {type} name description

vs.

* @param {type} name
*  description

we should adopt for the Drupal project the 2nd format, because it is closer to what we have for PHP.

So that is my at least current position: yes definitely adopt the JSDoc syntax, but have generally the same requirements, and where there are flexibilities in the JSDoc syntax, adopt a standard for formatting that is as close to how we do things in PHP as possible.

Can we all agree on that?

nod_’s picture

No problems there, agreed. And things like tag order, newline between tags, description on the next line and those sort of things, I'm happy to follow that.

attiks’s picture

#96

I was only reacting to this part, sorry for the confusion

Trying to re-invent the JSDoc wheel just because it doesn't work with api.d.o will get us in more trouble than it's worth.

A separate site would be far more beneficial (and preferable) than trying to merge it with api.d.o, maybe js.d.o? Then api.d.o can simply just link the JS files it finds to the js.d.o site and not not have to worry about parsing it at all.

I would prefer an integrated site (including KSS docs some day), but this should not stop use from launching separate sites as well.

markcarver’s picture

Yeah, no problems there, agreed.

But, again, not really the point I was making... I said exactly what I meant, but I guess I'll try to say it in a different way:

Yes, "documentation" is a top level sub-system. Yes, it's there to provide consistency and a singular voice for best practices and integration with api.d.o. That was born out of a necessity to document the PHP APIs of Drupal (which came first, I get it).

However, Drupal has come a very long way since then. It's a little different when we have made an entire language a dedicated top level sub-system. There is far more JS in Drupal than ever before.

Any "documentation" regarding it should really be underneath that sub-system and maintained by the component maintainer: @nod_; who understand the intricacies and concepts of the language and who is indeed the current subject authority.

We really shouldn't treat JS like PHP or have "parity" as the first thing on our minds here. Nor should we really continue to think that everything will "fit" on api.d.o.

It's OK to treat JS differently, it's a different language with different paradigms.... so yes, it would actually HELP if we had such a stark difference from the normal "API" site.

A different site that could be auto-generated by JSDoc itself instead of having to worry about maintaining yet more code to integrate something that already works out of the box with something else. A different site that isn't cluttered with all the other non-essentials to the task at hand: understanding the JavaScript APIs.

Btw, carVer with a "V"......

attiks’s picture

#100 100% agreed, we need to start to treat javascript as a separate and necessary part of Drupal.

jhodgdon’s picture

Sorry about the typo in your name markcarver. I do know your name, just a slip of the finger.

So... I think we're in pretty close agreement here, actually. And as far as who is the "Official Authority on the JS Doc Standards", I don't really care too much if it's nod_ or me or the Drupal Core maintainers or the Technical Working Group. I think we can all come to an agreement as a community, which is normally how we'd want all coding standards to be agreed to.

And let's move discussion about where/how to display a JSDoc site to this issue where we're already discussing that, not here: #25901: Parse/save/display JavaScript files

tizzo’s picture

tizzo’s picture

Project: Drupal Technical Working Group » Coding Standards
Component: Code » Coding Standards
tizzo’s picture

Status: Active » Fixed

This issue has been addressed in #2182153: [Meta] Document Drupal JavaScript using JSDoc and is already reflected in the Javascript API documentation and comment standards. Marking fixed.

cosmicdreams’s picture

Great! now can someone teach PhpStorm how to have these coding standards in a preset setting? https://youtrack.jetbrains.com/issue/WI-31028

markcarver’s picture

There's no need for a [custom] Drupal JS Coding Standards inspection (preset setting) in PHPStorm. Drupal (core)/community has standardized on using ESLint to assist with our JS coding standards. Just use the PHPStorm plugin https://plugins.jetbrains.com/plugin/7494 and it'll use the first .eslintrc* file(s) found (which is now included with core):

http://cgit.drupalcode.org/drupal/tree/.eslintignore,
http://cgit.drupalcode.org/drupal/tree/.eslintrc,
http://cgit.drupalcode.org/drupal/tree/core/.eslintrc

TravisCarden’s picture

@markcarver: I agree with your assessment with respect to the need for a custom PhpStorm style if the same effect can be achieved with the ESlint plugin. (If only we could do the same for PHP and CSS!) A handbook page someplace on setting it up would be a great addition.

TravisCarden’s picture

Actually, as they pointed out in the Jetbrains tracker issue, we conflated the concepts of an inspection and a code style. An inspection finds and marks issues and is handled very well (in theory) by the ESlint plugin. But the code style serves the different function of autoformatting and the like. In other words, one retroactively detects non-conformity and the other proactively prevents it. There's no conflict under the current architecture of the PhpStorm application, and that issue will go forward. This whole question seems quite secondary to the main point of this issue, but since it was brought up I wanted to be accurate about it.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

klausi’s picture

Removing tag.