ionic-team / stencil

A toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, and traditional web developers from a single, framework-agnostic codebase.
https://stenciljs.com
Other
12.5k stars 784 forks source link

feat: List external dependencies in documentation #3915

Open lawlesscreation opened 1 year ago

lawlesscreation commented 1 year ago

Prerequisites

Describe the Feature Request

We have multiple libraries of web components, when compiling the documentation it currently only lists any component that is part of the library and not external components being used.

It would be nice if you could somehow whitelist an array or glob that can be used when documenting dependencies of your component.

Describe the Use Case

<my-component> contains an <ion-badge>. If I said I want the dependency docs to include any component I use that contains "ion-*" then I would expect the documentation to say:

Depends on

Graph

graph TD;
  my-component --> ion-badge

I tried to implement this using custom-docs and the JsonDocsComponent but it didn't seem possible.

lawlesscreation commented 1 year ago

I tried writing my own documentation generator with the docs-custom type:

        {
            type: 'docs-custom',
            generator: (docs) => {
                docs.components.map((component) => {

                    function parseFile(contents: string) {
                        const dependencies = new Set();
                        const htmlTagRe = RegExp('<ion-[a-z\-]+((\/>)|( |>))','gi');
                        const matches = contents.matchAll(htmlTagRe);

                        for (const match of matches) {
                            let newMatch = match[0].replace(/</g, '').replace(/>/g, '').trim();
                            dependencies.add(newMatch);
                        }

                        // Delete tags already in the component dependencies array
                        component.dependencies.forEach(tag => {
                            dependencies.delete(tag)
                        });

                        // Sort the Set
                        const sortedDepsArray = Array.from(dependencies).sort();
                        const sortedDepsSet = new Set(sortedDepsArray);

                        // Add the missing dependencies
                        sortedDepsSet.forEach(tag => {
                            component.dependencies.push(tag as string);
                        });
                    }

                    fs.readFile(component.dirPath + '/' + component.fileName, 'utf-8', async (err, file) => {
                        if (err) throw err;

                        parseFile(file);
                        console.log(component);
                    });
                });
            },
            strict: true
        }

Which correctly adds the dependency to the custom docs data model:

  dependencies: [
    'ion-badge'
  ],
  dependencyGraph: {
    'my-component': [
      'ion-badge'
    ]
  },

But alas the dependency documentation in the component README.md is not updated. I'm not sure if the generator is modifying the JsonDocs model before or after the documentation in generated.

rwaskiewicz commented 1 year ago

Hey @lawlesscreation :wave:

I’d like to understand this feature request a little bit more.

We have multiple libraries of web components, when compiling the documentation it currently only lists any component that is part of the library and not external components being used. Can you describe how these libraries depend on one another, if at all?

For example, is there one library that each depends on: mermaid-diagram-2022-12-19-094156 Or, is each library dependent on the other: mermaid-diagram-2022-12-19-094310 Or maybe a mixture of both like so: mermaid-diagram-2022-12-19-094413


It would be nice if you could somehow whitelist an array or glob that can be used when documenting dependencies of your component.


contains an . If I said I want the dependency docs to include any component I use that contains "ion-*" then I would expect the documentation to say: Depends on - ion-badge

In your ideal scenario, is the list of dependencies just a set of <li>'s in the documentation, or is it a clickable link? Something else?

lawlesscreation commented 1 year ago

Thanks @rwaskiewicz, I'll try to answer:

Library structure

It's currently quite linear but I guess it could be a mixture of both. We're currently working like this:

graph TD;
  my-component --> lib-card --> ion-badge

"my-component" is an application level web component that contains the "lib-card" web component from our external library, which in turn contains a "ion-badge" component.

Though I wouldn't expect it to really know dependencies of dependencies, I'm not sure how it could know what's being used beyond the components it uses itself.

Would these be web components/html tag names (e.g. ion-button) only?

Yes, if my-component was:

  render() {
    return (
      <Host>
          <div>
            <my-card>A card</my-card> << component in same library
            <ion-badge>Badge</ion-badge> << component from external library
          </div>
      </Host>
    );
  }

I'd want some way of getting Stencil to parse "my-component" and look for anything that is my- and ion-.

Is there a reason you'd be interested in an allow/include-list, as a opposed to a deny/exclude-list?

Either is fine. I guess as long as it doesn't list standard HTML elements as a "dependency"

In your ideal scenario, is the list of dependencies just a set of <li>'s in the documentation, or is it a clickable link? Something else?

Correct, I'd just want it to say:

Depends on

If it's a component from the same library (my-card) then a link is great (it does that already). If it's a component not found in my local library then no link is fine.

lawlesscreation commented 1 year ago

In essence, I would like to make it clear what other web components my "my-component" depends on beyond what is actually included in the same library.

rwaskiewicz commented 1 year ago

Thanks @lawlesscreation! Makes sense to me - I'm going to label this feature request to gauge interest from the rest of the community!