-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat!: JSON doc generation #533
Conversation
(moved comments to PR description) |
@@ -33,16 +33,6 @@ describe('extractPackageName', () => { | |||
|
|||
}); | |||
|
|||
test('custom link formatter', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved this test to markdown.test.ts
src/docgen/util.ts
Outdated
remarks: docs.remarks.length > 0 ? docs.remarks : undefined, | ||
see: docs.link.length > 0 ? docs.link : undefined, | ||
deprecated: docs.deprecated === true ? true : undefined, | ||
deprecationReason: docs.deprecationReason, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can add more fields from this at any later point as needed (e.g. stability, examples, or other custom @ tags)
parentType: property.parentType, | ||
parentType: callable.parentType, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
small bug fix needed to get links working correctly
I want to say: what's the point of MarkDown anymore at this stage 😅 but I support the usability improvements |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like what you're doing, and I appreciate the effort. I'd prefer to see the MarkDown renderer factored out into its own visitor class. Seems like a neater separation of concerns, makes it easier to add new types of renders, and more in line with the final processing pipeline.
src/docgen/render/markdown.ts
Outdated
|
||
export const defaultLinkFormatter = (type: JsiiEntity) => { | ||
const name = type.fqn.split('.').pop()!; | ||
return `<a href="#${type.id}">${name}</a>`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the type comes from a different assembly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case we just shrug it off. This is just a default after all. The id is unique across assemblies, so in the worst case the link is invalid. You can see this in the example gist here, where if you click on a type named Construct
, the link doesn't take you anywhere.
I think this is good enough for the default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I suppose we could display no link if the type isn't from the current assembly. I'll leave this as a future enhancement for now since it's not too critical
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See I disagree with this.
In terms of user experience, a link that doesn't work seems worse than no link at all. How annoyed would you be if you clicked something that's obviously a link and nothing happened? You'd click a couple times more, and then start to distrust every other link you'd see.
I'd rather have that be in the initial implementation. Doesn't seem like a huge implementation stretch, but correct me if I'm wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, I see your point now - yeah dead links are a pretty bad experience. 😅
I've added another parameter to the linkFormatter
API to enable this behavior -- as of right now, linkFormatter
is expected to be a pure function, so the formatter needs extra info to make the determination of whether to create a link.
The formatting APIs are getting a bit heavy/awkward so I've added some more docs and marked them experimental for now. It might make sense eventually just require anyone that wants to customize the markdown linking and formatting etc. to just implement their own markdown renderer at the end of the day -- but for now I'd rather keep these (awkward) APIs just to avoid duplicating code between here and Construct Hub. But any/all suggestions are still welcome. 🙂
a6377c3
to
ef8d57b
Compare
@rix0rrr I've given a shot at refactoring all of the markdown-ification into a visitor class - definitely feels like an improvement. Let me know what you think. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd like to see the links changed. Let's not generate links that don't go anywhere.
Other than that, <3 this and ready to ship it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
Signed-off-by: github-actions <[email protected]>
"packageVersion": "3.3.187", | ||
"packageVersion": "3.3.188", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hrmmmmm. It looks like what's happening is that since most packages we generate have caret dependencies, the version of the referenced type isn't necessarily fixed.
I've been thinking about this for a while, including whether there's some better way to model this so that the package version stays fixed given the current assembly (e.g. by including the semver string from package.json instead) -- but it turns out that forces a lot of additional complexity onto downstream users.
For now I'm going to simply add some extra code that will make the snapshots stable by always linking to the same package version within unit tests (e.g. "1.2.3")
// may belong to dependency packages, which could be specified with caret | ||
// dependencies - this means the packageVersion of a type like | ||
// `construct.Construct` will be set to whichever version is installed. | ||
// This is okay in practice, but makes snapshot tests inconsistent. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this a problem though? Our snapshots will get updated during self-mutation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scratch that, its inconsistent over time you mean, unrelated to dependency upgrades 👍
Supersedes #481
Part of cdklabs/construct-hub-webapp#714 and cdklabs/construct-hub#142
Allows rendering language specific documentation to a JSON object in addition to a markdown string. This allows the consumer more flexibility to render the structure of the API reference as needed without regenerating markdown documents.
This PR builds upon #481 by cleaning up the JSON schema (in
schema.ts
) and also changing the markdown rendering logic to be based on the JSON output -- so the markdown rendering does not depend on anyTranspiledXxx
classes or interfaces.All headers now have anchor tags which default to the unique language-agnostic FQNs (e.g.
@aws-cdk/aws-s3.Bucket.parameter.scope
). Based on my research, all characters used in JSII FQNs (A-Za-z0-9_-/.@) are allowed as URL fragments, and are also allowed as id's in HTML5, so this is a reasonable default.This PR also extends the notion of fully qualified names to all "entities" in the document (methods, properties, enum members, and even method parameters) denoted by the "id" fields within the JSON schema, so that any section of a document can be uniquely linked - not just types. The
JsiiEntity
interface inschema.ts
is intended to encapsulate any information that should be needed to render a link, including the package version it's from (this is necessary for Construct Hub to be able to link to the correct versions of packages).Markdown generation can now be customized using three hooks:
anchorFormatter: (type: JsiiEntity) => string
- customize the IDs given to anchors tags that are placed next to every header in the document, so that any part of the API reference can be directly linkedlinkFormatter: (type: JsiiEntity, metadata: AssemblyMetadataSchema) => string
- customize how links should be rendered when they appear in tables, descriptions, etc. -- e.g. to include logic to "link to another page"typeFormatter?: (type: TypeSchema, linkFormatter) => string
- customize how composite types should be rendered when they include nested types - this allows functionality like the screenshot below:See
markdown.test.ts
for an example of how the markdown rendering hooks would be used to format links for Construct Hub.Examples:
@aws-cdk/aws-ecr Python API.json: https://gist.github.com/Chriscbr/731b315808faaf2a2161d686ce248368
@aws-cdk/aws-ecr Python API.md: https://gist.github.com/Chriscbr/d0833a9ecce258dead648a63253b8b0e
BREAKING CHANGE:
Documentation.render
is now namedDocumentation.toMarkdown
. In addition, the options parameter for this method has changed.TranspiledType
is no longer exported.