webcomponents / custom-elements-manifest

A file format for describing custom elements
BSD 3-Clause "New" or "Revised" License
361 stars 26 forks source link

Add recommended JSDoc tags #42

Open justinfagnani opened 3 years ago

justinfagnani commented 3 years ago

Many analysis tools will use JSDoc tags to determine what web component specific features. To keep from fragmenting the ecosystem around different sets of JSDoc, we should make a recommended set of tags.

Tags will need to document the features in the CustomElement schema kind:

thepassle commented 3 years ago

Currently the analyzer supports the following JSDoc:

JSDoc Description
@attr,
@attribute
Documents attributes for your custom element
@prop,
@property
Documents properties for your custom element
@csspart Documents your custom elements CSS Shadow Parts
@slot Documents the Slots used in your components
@cssprop,
@cssproperty
Documents CSS Custom Properties for your component
@fires,
@event
Documents events that your component might fire
@tag,
@tagname
Documents the name of your custom element

tagname and demos are currently not supported, but should be very trivial to implement 👍

I'd be curious to hear @JanMiksovsky s feedback on this as well, since he mentioned this in the latest meeting 🙂

JanMiksovsky commented 3 years ago

Thanks for sharing this set of jsDoc tags. These generally covers our own jsDoc tags, with a few minor differences.

While jsDoc defines synonyms for many tags, I wonder how necessary it is to support synonyms for new tags. Since this type of component tooling is new, it might be better to just introduce a single tag for each idea not already covered in jsDoc. FWIW these seem clear to me: @attribute, @cssproperty, @tag, but you could also just decide what you look and say "Use these".

thepassle commented 3 years ago

I'm currently working on a plugin system for the analyzer, and that will make enabling custom jsdoc pretty trivial through the use of a plugin. Consider the following example from thomas:

source code:

class MyElement extends HTMLElement {

  /**
   * @type string
   * @editvia textarea[rows=2]
   */
  message = '';
}

desired output:

{
  "kind": "field",
  "name": "message",
  "type": {
    "text": "string"
  },
  "default": "''",
+ "editvia": "textarea[rows=2]"
},

plugin code: custom-elements-manifest.config.js

import ts from 'typescript';

export default {
  plugins: [
    function myPlugin() {
      return {
        // Runs for each module
        analyzePhase({node, moduleDoc}){
          switch (node.kind) {
            case ts.SyntaxKind.ClassDeclaration:
              const className = node.name.getText();

              node.members?.forEach(member => {
                const memberName = member.name.getText();

                member.jsDoc?.forEach(jsDoc => {
                  jsDoc.tags?.forEach(tag => {
                    if(tag.tagName.getText() === 'editvia') {
                      const description = tag.comment;

                      const classDeclaration = moduleDoc.declarations.find(declaration => declaration.name === className);
                      const messageField = classDeclaration.members.find(member => member.name === memberName);

                      messageField.editvia = description
                    }
                  });
                });
              });

              break;
          }
        },
        // Runs for each module, after analyzing, all information about your module should now be available
        moduleLinkPhase({moduleDoc}){
          // console.log(moduleDoc);
        },
        // Runs after all modules have been parsed, and after post processing
        packageLinkPhase(customElementsManifest){
          // console.log(customElementsManifest);
        },
      }
    }
  ]
}
justinfagnani commented 3 years ago

The spec doesn't refer to them as "CSS parts"

They are called "CSS Shadow Parts" and they're a part os the CSS spec, so while within the context of CSS "part" might mean a specific thing, outside it might not. This doc format covers JS, HTML and CSS concepts and "part" is a very general term, so I think it's best to disambiguate. Similarly I don't think we'd want to document CSS variables as @variable or @property.

The idea about part class names is interesting... I wonder if it should be more explicit that the additional name is a class name in case there's other metadata we want to add in the future. One such thing might be source info on an exported part so the original docs can be found.