Complete documentation for stencil components with jsdoc, specifically a component description? - jsdoc

I'm in the process of creating a web components library with stencil.js. I would like to leverage the docs-readme output capability, but am having to do a lot of trial and error on what comments will actually be output into the documents.
The specific issue I'm having right now is that I'm not able to get documentation for the component itself to generate with the readme. For example:
/**
* This is a description of the component that I would like to generate in the readme.md for MyComponent
*/
#Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true,
})
/** I've also tried this comment style and this location, but no dice */
export class MyComponent {
...
}
According to the jsdoc documentation it seems like I should be able to document the class, but nothing seems to work. Is there an exhaustive list of what stencil will and won't actually generate documentation for?

You need to place the documentation of the web component (element class) itself to the (partially) generated readme.md. Only the documentation of the class members (properties/attributes, methods) and of the CSS variables is expected in the source files (.tsx, .css).
(Update: See the UPDATE section below about the purpose of the component comment.)
Insert the documentation to src/components/my-component/readme.md above the following line:
<!-- Auto Generated Below -->
The content below this line will be generated using the JSDoc comments in your source files.
Example
# x-eyes
Shows a pair of eyes following movements of ...
<!-- Auto Generated Below -->
See the full readme, TS source and CSS source of the example above.
UPDATE
Actually, if you add a documentation comment to the component as you intended:
/**
* Alternative summary...
*/
#Component({ tag: 'x-eyes', styleUrl: 'x-eyes.css' })
export class XEyesElement {
it will be used, but not in the readme file; but only in the docs property of the docs-json or docs-vscode output targets:
{
"filePath": "./src/components/x-eyes/x-eyes.tsx",
"encapsulation": "shadow",
"tag": "x-eyes",
"docs": "Alternative summary...",
"readme": "# <x-eyes>\n\nShows a pair of eyes following movements ...
If you do not add the documentation comment to the component, the content of the docs property will be extracted from the first part of your readme.md, between the main title and the first sub-title (initiated by #):
{
"filePath": "./src/components/x-eyes/x-eyes.tsx",
"encapsulation": "shadow",
"tag": "x-eyes",
"docs": "Shows a pair of eyes following movements of ...",
"readme": "# <x-eyes>\n\nShows a pair of eyes following movements ...
So, if you want to change the description summary of your component to be shorter or different than the introductory part of your readme.md, you can insert the component comment to your component source.

Related

Dynamically inject content into JSDoc #example

I'm using JSDoc to document my javascript API.
I have an #example where I exhibit a minimized loader script (similar to the Google Analytics script). The loader script loads additional javascript from https://<server>/myProduct/lib/script.js.
My JSDoc documentation is bundled with myProduct, so there are aways /myProduct/lib/script.js and /myProduct/docs/ side-by-side. However, myProduct can be hosted by my customers anywhere, so I don't know what the <server> is.
I would like to be able to use document.location.href to detect current browser URL, and display a working loader script in my #example, so that customer can simply copy & paste a working script from documentation without having to manually edit the <server> part.
My question is: Does JSDoc offer any means to dynamically inject content into #example?
I could just manually edit the JSDoc output and include some custom javascript manually, which replaces <server> with the actual current server on run-time. However, this would be tedious to do every time my documentation updates.
No, JsDoc doesn't provide for injecting external content, and while it is certainly possible to create a JsDoc plugin to include external content during document generation, I don't think this would get you where you need to be.
I think the simplest answer would be to post-process the output of JsDoc to add a simple script, like
<script>
// retrieve the hostname from the current url.
const getServiceHostName = () =>
document.location.href.replace(/http:\/\/([\/]+)\/.+$/, '$1');
// replace the content of the span#service-host with the current hostname.
document.onload = function () {
document.getElementById("service-host").textContent=getServiceHostName();
};
</script>
to your html files just above the </body> tag.
Then, in the example content, insert a <span id="service-host"></span> where you'd like the service hostname to appear.
Another approach might be to take advantage of the fact that JsDoc passes the content attached to the #description tag directly into the html output.
So, this appears to do the expected:
/**
* Hostname: "<span id="service-host">hostname</span>"
*
* <script src="https://code.jquery.com/jquery-3.6.0.min.js"
* integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
* crossorigin="anonymous"></script>
*
* <script>
* $(document).ready(function() {
* $("#service-host").html(document.location.href);
* });
* </script>
*
* #name How-To-Monkey-Patch-JsDoc
*
*/
Note that the content of #example is wrapped in <pre><code>...</code></pre> in the html output which will definitely cause you problems, but it should be easy to post-process the html inline using the code above, by adding some recognizable token (perhaps [[HOSTNAME]]) into the example content and on document load, replace it with the desired value.
Please note also that this approach has the possibility of opening your docs to security issues, which is why I'd use the first solution above.

How do I not include scripts and clientlibs in an experience fragment when exporting to Adobe Target?

I'm trying to build an experience fragment (XF) template in AEM 6.5. We have some custom clientlibs that I want to include when designers are authoring the experience fragment but I don't want to include when the experience fragment is injected via Adobe Target as the clientlibs will already be included on the base page template.
I want the clientlibs on the XF template so components render properly while designing. I've tried building a new page component based on /libs/cq/experience-fragments/components/xfpage and then checking the runmode for author or publish and using the result of that in a data-sly-test to conditionally include them. But I think because the Export to Target option happens on Author, it's including the scripts in the html output when it's exported to Target.
How do I conditionally include clientlibs during authoring of an XF, but not include them when the experience fragment is exported to target and added to a page from there?
There are couple of things you need to do in order to achieve this.
AEM offers the Link Rewriter Provider Interface. This is a ConsumerType interface that you can implement in your bundles, as a service.
It bypasses the modifications AEM performs on internal links of an HTML offer as rendered from an Experience Fragment. This interface allows you to customize the process of rewriting internal HTML links to align with your business needs.
To use the interface you first need to create a bundle containing a new service component that implements the Link Rewriter Provider interface.
This service will be used to plug into the Experience Fragment Export to Target rewriting in order to have access to the various links.
import com.adobe.cq.xf.ExperienceFragmentLinkRewriterProvider;
import com.adobe.cq.xf.ExperienceFragmentVariation;
import org.osgi.service.component.annotations.Service;
import org.osgi.service.component.annotations.Component;
#Component
#Service
public class GeneralLinkRewriter implements ExperienceFragmentLinkRewriterProvider {
#Override
public String rewriteLink(String link, String tag, String attribute) {
return null;
}
#Override
public boolean shouldRewrite(ExperienceFragmentVariation experienceFragment) {
return false;
}
#Override
public int getPriority() {
return 0;
}
}
shouldRewrite
You need to indicate to the system whether it needs to rewrite the links when a call is made for Export to Target on a certain Experience Fragment variation. You do this by implementing the method:
shouldRewrite(ExperienceFragmentVariation experienceFragment);
For example:
#Override
public boolean shouldRewrite(ExperienceFragmentVariation experienceFragment) {
return experienceFragment.getPath().equals("/content/experience-fragment/master");
}
This method receives, as a parameter, the Experience Fragment Variation that the Export to Target system is currently rewriting.
In the example above, we would like to rewrite:
links present in src
href attributes only
for a specific Experience Fragment:
/content/experience-fragment/
Any other Experience Fragments that pass through the Export to Target system are ignored and not affected by changes implemented in this Service.
rewriteLink
For the Experience Fragment variation impacted by the rewriting process, it will then proceed to let the service handle the link rewriting. Everytime a link is encountered in the internal HTML, the following method is invoked:
rewriteLink(String link, String tag, String attribute)
As input, the method receives the parameters:
link
The String representation of the link that is currently being processed. This is usually a relative URL pointing to the resource on the author instance.
tag
The name of the HTML element that is currently being processed.
attribute
The exact attribute name.
If, for example, the Export to Target system is currently processing this element, you can define CSSInclude as:
<link rel="stylesheet" href="/etc.clientlibs/foundation/clientlibs/main.css" type="text/css">
The call to the rewriteLink() method is done using these parameters:
rewriteLink(link="/etc.clientlibs/foundation/clientlibs/main.css", tag="link", attribute="href" )
When you create the service you can make decisions based on the given input, and then rewrite the link accordingly.

Sample code for KeystoneJS 5 custom fields?

I'm interested in writing custom fields for KeystoneJS 5. The documentation is here, but I find it somewhat opaque (i.e., not fully explicatory). Is there sample code available? I looked in 'demo projects' and 'test projects' in the Keystone repo, but didn't see anything.
KeystoneJs custom fields are poorly documented and not easily accessible. in fact the whole concept of writing the whole custom field may be overkill.
here is the example one core team member has put copied form the test-project. - https://github.com/MadeByMike/keystone-custom-field/blob/7caf0139c189eadda1884a86073c6945bdd6ff05/index.js#L15
this is what you need to do:
1. you need to create a folder for the field
2. you can copy the Text field implementation to start with
3. there index.js file must export specific object (default export) like this ( I have added some comment for each line)
{
type: 'Stars', // name of the implementation
implementation: Stars, // implementation itself
views: { // all views are required you can copy the implementation from Text field)
Controller: Integer.views.Controller, // it is using controller from Integer field type
Field: require.resolve('./views/Field'), // field which goes into edit page or create dialog
Filter: Integer.views.Filter, // this adds filters in the list page
Cell: require.resolve('./views/Cell'), // view for list page where you usually see the text, for Relationship it is rendered as link.
},
adapters: {
mongoose: MongoIntegerInterface, // mongoose adapter specific inplementation
knex: KnexIntegerInterface, // knex adapter specific implementation,.
},
}
create views for each type (Field, Filter, Cell etc.)
import the field (default import) in the schema definition and use it like regular field. any custom option is passed on to the custom implementation.

Doxygen: extract specific doxygen defines into separate documentaion

I have some source code (STM32 Peripherial Lib) with existing doxygen parameters which my Doxygen Builds without Problems.
For my project I want to generate a document with all functions in each file and a specific information which I want to add to the functions. But I want to keep the old informations for another doxygen configuration.
Is that possible?
I already added this for testing:
\ifnot "SECTION_DEFINE"
<normal Doxygen Parameters from original Source Code>
\elsif "SECTION_DEFINE"
#brief Function Check TODO
\endif
With this I could deactivate the existing documentation, but I need to write this \ifnot \elsif \endif to every function.
Can I just declare a Tag and only generate the documentation for this specific tag?
Kind regards
Andi
You may create a "related page" where only your additional information will be displayed with the \xrefitem command. As \xrefitem will also create a special text section within your original documentation you may want to combine it with your original idea of using section labels and conditional documentation. To top this concept off, use aliases in order to make your documentation more readable.
Consider this example code:
/** ST documentation
* foobar
* \exclusive for andi's function \endif
*/
void andreas(void);
/** ST documentation
* foobar
* \exclusive for beni's function \endif
*/
void benjamin(void);
You may use this alias in your Doxyfile: exclusive=\if SECTION_DEFINE \xrefitem viparea "Exclusive" "VIPs".
As long as SECTION_DEFINE is not defined, the "exclusive" information will not be included in your documentation. As soon as this section is defined, a "related page" (here: viparea.html) is created in your HTML documentation containing your documented items (here: andreas and benjamin) with the exclusive paragraph behind the command. The result:

Visual Studio Code with Native Script does not recognize all Native Script components

Visual Studio Code with Native Script does not recognise Native Script components sometimes in the component XML. I have one from the official tutorial and in it the ActionBar is recognized - but GridLayout is not:
'GridLayout' is not a known element:
1. If 'GridLayout' is an Angular component, then verify that it is part of this module.
2. To allow any element add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component.
XML looks like this:
<ActionBar title="Groceries">
<!-- On iOS devices, <ActionItem>s are placed from left to right in sequence; you can override that (as the code above does) by providing an ios.position attribute. -->
<ActionItem text="Share" (tap)="share()" android.systemIcon="ic_menu_share_holo_dark" ios.systemIcon="9" ios.position="right"></ActionItem>
</ActionBar>
<GridLayout rows="auto, *">
<!-- add-bar necessary since we moved the page up 20 over the status bar on iOS-->
<GridLayout row="0" columns="*, auto" class="add-bar">
<TextField #groceryTextField [(ngModel)]="grocery" hint="Enter a grocery item" (returnPress)="add()" col="0"></TextField>
<Image src="res://add" (tap)="add()" col="1"></Image>
</GridLayout>...
It seems totally arbitrary since for example StackLayout is no problem in another XML in same project.
As suggested in the error log make sure that you have included NO_ERRORS_SCHEMA in the respective NgModule (if using lazily loaded modules include the schema there as well)
import { NgModule, NO_ERRORS_SCHEMA } from "#angular/core";
#NgModule({
schemas: [NO_ERRORS_SCHEMA],
//... more code follows here
Side note: it might be just an incomplete snippet but still... the parent GridLayout does not have an enclosing tag
In my case, it was happening just for one component html though NO_ERRORS_SCHEMA was included in respective module of that file, deleting and creating that file solved the issue for me strange but it did happen.