Skip to content
This repository has been archived by the owner on Sep 26, 2022. It is now read-only.

New api generator discussion #26

Open
Graphmaxer opened this issue Oct 12, 2020 · 21 comments
Open

New api generator discussion #26

Graphmaxer opened this issue Oct 12, 2020 · 21 comments
Labels
enhancement New feature or request
Milestone

Comments

@Graphmaxer
Copy link
Contributor

Currently we are using sveltedoc-parser to generate JSON files that we can use in the website as API documentation.

Svelte is moving to Typescript and components too. Multiple options are available :

  • Keep documenting components inside the .svelte file via comments. With this sveltedoc-parser is fully functional with props/slots/events documentation.
  • Move documentation to the typing definitions, inside .d.ts files. We need to change the script to generate the JSON files. We can use native typescript compiler API, tsdoc parser, api-extractor or typedoc. With this option we can only type props until this get approved or similar.

I started to implement a mix between sveltedoc-parser and typescript compiler api in this PR : #25.

Feel free to discuss about it.

@Graphmaxer Graphmaxer changed the title New api generator New api generator discussion Oct 12, 2020
@TheComputerM
Copy link
Owner

Yeah, and I also have been meaning to revamp the API table style, any suggestions/screenshots are welcome.

@TheComputerM TheComputerM added this to the Version v1.0 milestone Oct 18, 2020
@TheComputerM TheComputerM added the enhancement New feature or request label Oct 18, 2020
@soft-decay
Copy link

@Graphmaxer You've mentioned keeping the documentation in the .svelte files using sveltedoc-parser, but it seems to me the best solution in the long run would be to migrate the components to typescript (<script lang='ts'>) and use typedoc on them, probably by running it on the content of the <script> tag (extracted using the svelte parser).

I tested the project with typescript components and both build and test are passing. The only part I'm not too sure about yet is how to correctly expose the types for library usage. Importing from svelte-materialify/src or svelte-materialify/src/components/<ComponentName> correctly shows the typings from the .svelte files, but importing from svelte-materialify still points to svelte-materialify/@types. Would it be possible to generate d.ts declaration files from the .svelte to avoid having to maintain the type files?

I'd like to work on this if you have not already started something. I feel using this approach would be better because it provides both typing and documentation directly in the component file, thus reducing file juggling and documentation duplication.

@Graphmaxer
Copy link
Contributor Author

I agree with you @soft-decay, typescript is probably the good way to document components. I don't know any solution about the library usage, i think the svelte team is also figuring out the best way to distribute libraries with typings (RFC). And feel to free to experiment and try, i'm not working on this currently.

@TheComputerM
Copy link
Owner

Ok then, we have two approches:

  1. Use lang=ts.
  2. Generate .d.ts files using sveltedoc-parser

Using the 1 method, this will be much better to maintain but we will need to also install typescript when doing an advanced install and I fear the development times would be slower (please correct me if I am wrong). Using the 2 method would be a lot easier but would not provide good definitions. I am personally inclined to the 1 method (we can also provide a custom preprocessor instead of using svelte-preprocess to speed things up?).

Please list anything that I may have missed.

@soft-decay
Copy link

@TheComputerM TL; DR I wanted 1 but I think 2 would work well in the meantime.

I've encountered a few problems while experimenting.

  1. sveltedoc-parser does not support typescript inside script tags (this feature), which makes the parsing process rather convoluted when using <script lang="ts"> (i.e. You need a different parser for the script block, then transform it and pass it to sveltedoc-parser, then merge the information from the two parsers and produce a new json file).
  2. Generating declaration files from the content of <script lang="ts"> produces incomplete/incorrect definitions (e.g. No interface, non-optional props, etc).

Because of that, I think it would be best to :

  • Document props inside the components. This will always be relevant regardless of typescript usage. When/If the components are migrated to typescript, the comments will still be usable (even if some annotations would become redundant, e.g. @type).
  • Generate the *.d.ts files from the sveltedoc-parser *.json files. This would be simple using templates (e.g. mustache) but maybe sveltedoc-parser already can export declaration files? (I did not find that it can)

Of course I do not know the full extend of what types you would like to provide, but I think jsdoc could be enough. It would be possible to update the @type {<type>} annotations to : <type> when typescript becomes available in sveltedoc-parser.

@soft-decay
Copy link

So I worked on a declaration (d.ts) generator and I have a first working draft. I would like some input on how to improve it. Here's how it plugs into the api script:

  1. Generate a document with sveltedoc-parser using generateJSON (which now also returns the produced document)
  2. Pass the generated document to the typings generation function (generateTypings)
  3. The document is sent to a compiled handlebars template which does the following:
    1. Add basic hard-coded imports (right now { SvelteComponent } from './shared')
    2. Add known imports from known types present in the document. This is less than ideal, but it is necessary to import unknown types like RippleOptions)
    3. Populate an interface with the visibility: 'public' (i.e. exported) props:
      1. Add documentation if necessary (needs at least a description, default value, or non-type keywords)
      2. Add type annotation (?: <type>)
      3. Export a declared class with the props interface (like in the current declaration files)
    4. Returns a string
  4. The resulting declaration string is saved in a file in ./@types/<ComponentName>.d.ts

A small number of manually created declarations would have to be to kept in a separate folder for step 2.2. I spotted these:

  • SvelteComponent (from ./shared) in all components
  • RippleOptions (from ./Ripple)
  • TransitionConfig and transition functions (from svelte/transition)

You can check the changes I made in PR #76.

@TheComputerM
Copy link
Owner

I feel like storing all the components in a single .d.ts file is better. Also everything has to be re-hauled as there is a better way to write definitions now.

@Graphmaxer
Copy link
Contributor Author

Nice work here @soft-decay, I think that the Svelte team is changing to SvelteComponentTyped instead of SvelteComponent recently. They are also talking about Svelte 4.0 which probably come with SvelteKit in 2021 and also with typed components. So maybe your work should be used right now because the current api generator is not working. And in the future we should switch to official typed components with Svelte 4.0.

@soft-decay
Copy link

For sure I was not expecting this to be a permanent solution, just a way to reduce maintenance/effort on the typings in the short term. The new SvelteComponentTyped is a really good thing, but I don't think that it resolves the issue of the api-generator, it just changes the format of the declaration files. The declarations could be generated using the SvelteComponentTyped declaration and definitely could all be bundled in a single declaration file. It just means adjusting the generation template.

Should I go for it (same steps described above but with SvelteComponentTyped and all in a single file)? A single file would also remove the need for step 2.ii, which is a nice plus.

@Graphmaxer
Copy link
Contributor Author

Graphmaxer commented Dec 3, 2020

For the single file, go for it and for the usage of SvelteComponentTyped, i don't know if we should switch to this, it is very new and i don't know if the language tools (extension vor vscode) is working properly with it. We should maybe wait and switch to SvelteComponentTyped in a second step.

@soft-decay
Copy link

soft-decay commented Dec 4, 2020

From what I tested, SvelteComponentTyped works out of the box in vscode. It seems like the only requirement is to update dependencies to "svelte": "^3.31.0" (both dev and peer).

The bundled declarations file is over 2000 lines, but here is a snippet:

import { SvelteComponentTyped } from 'svelte'
import { TransitionConfig, blur, crossfade, draw, fade, fly, scale, slide } from 'svelte/transition'
import { RippleOptions } from './@types/Ripple'

interface AlertProps {

  class?: string;

  /**
   * @default true
   */
  visible?: boolean;

  transition?: any;

  transitionOpts?: any;

  /**
   * @default false
   */
  dense?: boolean;

  /**
   * @default false
   */
  outlined?: boolean;

  /**
   * @default false
   */
  text?: boolean;

  /**
   * @default false
   */
  tile?: boolean;

  /**
   * @default false
   */
  dismissible?: boolean;

  /**
   * @default false
   */
  border?: boolean;

  /**
   * @default false
   */
  coloredBorder?: boolean;

}

export declare class Alert extends SvelteComponentTyped<AlertProps> {}

There is still a lot to be done for the component typings and documentation.
I Also included a list of known imports at the start of the bundle.

What else would make it better and easier to use? I'm thinking adding events and slots.

Right now index.d.ts can be generated with yarn api.

@Graphmaxer
Copy link
Contributor Author

Graphmaxer commented Dec 4, 2020

Looks good to me ! Nice work @soft-decay ! 👍

We can also use the default attribute of SvelteComponentTyped for default value of props.

@TheComputerM
Copy link
Owner

Also we have to parse events, slots and even sass variables (know any good way to do that?).

@soft-decay
Copy link

  • @Graphmaxer Thanks. I did not see that there was a way to set defaults in the generics. Can you link me to what you're referring to?
  • I think events and slots are parsed by sveltedoc-parser, I'll check.
  • For sass variables, I have no idea. Do you mean something like sass-variable-parser? But I don't know the end goal for them. Is it just for documenting the website?

@TheComputerM
Copy link
Owner

TheComputerM commented Dec 4, 2020

This is better for sass https://github.com/mleg/sass-vars-to-js-example, @soft-decay we can customize the variables in svelte materiaify so it is needed to show what variables can be customized.

@Graphmaxer
Copy link
Contributor Author

@soft-decay You can see it here, should with default event/prop/slot.

@soft-decay
Copy link

@Graphmaxer Are you referring to the 3rd generic param? That would be for slots, and the default keyword here refers to the default slot. You can also see it in the declaration. If that is not it, I'm sorry I could not see what you meant.

@TheComputerM typed-scss-modules seems pretty good. I'll try it and see if it works well enough for the project's setup.

@Graphmaxer
Copy link
Contributor Author

@soft-decay Yes exactly, in this RFC, they also say :

This would not be a breaking change to the existing definition because of the any type by default for props/events/slots.

this default parameter should work with props/events/slots (need testing to be sure).

@soft-decay
Copy link

soft-decay commented Dec 4, 2020

@Graphmaxer I see what you're saying, but my understanding is that it refers to the default slot, that is, the unnamed slot. For example :

import { SvelteComponentTyped } from 'svelte';

export class MyComponent extends SvelteComponentTyped<{}, {}, { default: { numberProp: number } }> {}

lets you do this (because the unnamed slot is the default slot) :

<script lang="ts">
  import { MyComponent } from "myModule";
</script>

<MyComponent let:numberProp>{{ numberProp }}</MyComponent>

But this :

import { SvelteComponentTyped } from 'svelte';

export class MyComponent extends SvelteComponentTyped<{}, {}, { content: { numberProp: number } }> {}

Let you do this :

<script lang="ts">
  import { MyComponent } from "myModule";
</script>

<MyComponent>
  <div slot="content" let:numberProp>{{ numberProp }}</div>
</MyComponent>

In both case they would be typed as a number. Let me know if I missed something, but I did not see a way to set default values directly on the type (a example syntax would help understand). Right now they are set throught the @default jsdoc annotations.

@Graphmaxer
Copy link
Contributor Author

@soft-decay You're right. I misunderstood this default attribute ^^.

@alexprey
Copy link

Hi, I'm plan to start implement the TS support in sveltedoc-parser (KatChaotic/sveltedoc-parser#34), but actually I dont use svelte with TS and it will be very nice if you have few examples with typescript svelte components

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants