Skip to content
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

Add lit-labs/context docs #1100

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,998 changes: 3,998 additions & 0 deletions packages/lit-dev-api/api-data/lit-2/pages.json

Large diffs are not rendered by default.

568 changes: 406 additions & 162 deletions packages/lit-dev-api/api-data/lit-2/symbols.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions packages/lit-dev-content/site/_includes/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@
{{- pipe() -}} {{- type(item) -}}
{%- endfor -%}

{%- elif t.type == 'intersection' -%}
{%- set pipe = joiner(' & ') -%}
{%- for item in t.types -%}
{{- pipe() -}} {{- type(item) -}}
{%- endfor -%}

{%- elif t.type === 'indexedAccess' -%}
{{- type(t.objectType) }}[{{ type(t.indexType) }}]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<li{% if child.url == page.url %} class="active"{% endif %}>
<a href="{{ child.url | url }}">
{{ child.title }}
{% if child.labs == true %}
{% if child.labs == true or child.labs == "true" %}
<img class="labs" src="/images/alerts/labs.svg" alt="labs" loading="lazy" fetchpriority="low" />
{% endif %}
</a>
Expand Down
2 changes: 1 addition & 1 deletion packages/lit-dev-content/site/_includes/docs-nav.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
<li{% if child.url == page.url %} class="active"{% endif %}>
<a href="{{ child.url | url }}">
{{ child.title }}
{% if child.labs == true %}
{% if child.labs == true or child.labs == "true" %}
<img class="labs" src="/images/alerts/labs.svg" alt="labs" loading="lazy" fetchpriority="low" />
{% endif %}
</a>
Expand Down
1 change: 1 addition & 0 deletions packages/lit-dev-content/site/docs/api/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
title: "{{ data.title }}"
eleventyNavigation:
key: "{{ data.title }}"
labs: "{{ data.labs }}"
parent: API
apiPath: /docs/api
---
2 changes: 2 additions & 0 deletions packages/lit-dev-tests/src/check-no-todos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const api_pages_to_check = [
pathLib.resolve(siteOutputDir, 'docs/api/static-html/index.html'),
pathLib.resolve(siteOutputDir, 'docs/api/styles/index.html'),
pathLib.resolve(siteOutputDir, 'docs/api/templates/index.html'),
// @lit-labs/context
pathLib.resolve(siteOutputDir, 'docs/api/context/index.html'),
];

const checkNoTodos = async () => {
Expand Down
81 changes: 64 additions & 17 deletions packages/lit-dev-tools-cjs/src/api-docs/configs/lit-2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ const gitDir = pathlib.join(workDir, 'repo');
const litDir = pathlib.join(gitDir, 'packages', 'lit');
const srcDir = pathlib.join(litDir, 'src');

const contextDir = pathlib.join(gitDir, 'packages', 'labs', 'context');
const contextSrcDir = pathlib.join(contextDir, 'src');

/**
* lit.dev API docs configuration for Lit 2.x
*/
Expand All @@ -24,7 +27,6 @@ export const lit2Config: ApiDocsConfig = {
commit: 'c134604f178e36444261d83eabe9e578c1ed90c4',
workDir,
gitDir,
tsConfigPath: pathlib.join(litDir, 'tsconfig.json'),
pagesOutPath: pathlib.resolve(workDir, 'pages.json'),
symbolsOutPath: pathlib.resolve(workDir, 'symbols.json'),
typedocRoot: pathlib.join(root, 'packages'),
Expand All @@ -36,24 +38,51 @@ export const lit2Config: ApiDocsConfig = {
},
],

entrypointModules: [
pathlib.join(srcDir, 'async-directive.ts'),
pathlib.join(srcDir, 'decorators.ts'),
pathlib.join(srcDir, 'directives/'), // Entire directory
pathlib.join(srcDir, 'directive.ts'),
pathlib.join(srcDir, 'directive-helpers.ts'),
// Don't include html.ts because it is already re-exported by index.ts.
// pathlib.join(srcDir, 'html.ts'),
// Don't include hydration because it's not ready yet.
// pathlib.join(srcDir, 'hydrate.ts'),
// pathlib.join(srcDir, 'hydrate-support.ts'),
pathlib.join(srcDir, 'index.ts'),
// Don't include polyfill-support.ts because it doesn't export anything.
// pathlib.join(srcDir, 'polyfill-support.ts'),
pathlib.join(srcDir, 'static-html.ts'),
packages: [
// 'lit' module documentation
{
tsConfigPath: pathlib.join(litDir, 'tsconfig.json'),

entrypointModules: [
pathlib.join(srcDir, 'async-directive.ts'),
pathlib.join(srcDir, 'decorators.ts'),
pathlib.join(srcDir, 'directives/*'), // Entire directory
pathlib.join(srcDir, 'directive.ts'),
pathlib.join(srcDir, 'directive-helpers.ts'),
// Don't include html.ts because it is already re-exported by index.ts.
// pathlib.join(srcDir, 'html.ts'),
// Don't include hydration because it's not ready yet.
// pathlib.join(srcDir, 'hydrate.ts'),
// pathlib.join(srcDir, 'hydrate-support.ts'),
pathlib.join(srcDir, 'index.ts'),
// Don't include polyfill-support.ts because it doesn't export anything.
// pathlib.join(srcDir, 'polyfill-support.ts'),
pathlib.join(srcDir, 'static-html.ts'),
],
},
// @lit-labs/context documentation
{
tsConfigPath: pathlib.join(contextDir, 'tsconfig.json'),
entrypointModules: [
pathlib.join(contextSrcDir, 'index.ts'),
pathlib.join(contextSrcDir, 'lib/context-request-event.ts'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need these other files as entrypoint modules? Since we want everything importing from index, can typedoc not just find them in the module graph?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree - I have to investigate this now that I have stabilized updating all the underlying stuff & fixed many other confounding issues.

Previously when I only used the entrypoint we only got a small cross section of APIs generated. See https://pr1092-ec9e4af---lit-dev-5ftespv5na-uc.a.run.app/docs/api/context/ as an example.

But many things have been fixed since then & I understand what is going on better now. Will try this again to clean it up.
Great comment!

pathlib.join(contextSrcDir, 'lib/create-context.ts'),
pathlib.join(contextSrcDir, 'lib/controllers/context-consumer.ts'),
pathlib.join(contextSrcDir, 'lib/controllers/context-provider.ts'),
pathlib.join(contextSrcDir, 'lib/decorators/provide.ts'),
pathlib.join(contextSrcDir, 'lib/decorators/consume.ts'),
],
},
],

symbolOrder: ['LitElement', 'ReactiveElement'],
symbolOrder: [
'LitElement',
'ReactiveElement',
/** @lit-labs/context symbol ordering */
'createContext',
'consume',
'provide',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add ContextConsumer, ContextProvider, and ContextRoot here for now.

],

pages: [
{
Expand Down Expand Up @@ -127,6 +156,12 @@ export const lit2Config: ApiDocsConfig = {
v1: 'api/lit-element/LitElement/',
},
},
// Add @lit-labs/context page.
{
slug: 'context',
title: 'Context',
labs: true,
},
],

pageForSymbol(node): string {
Expand All @@ -139,6 +174,10 @@ export const lit2Config: ApiDocsConfig = {
return 'decorators';
}

if (entrypoint.includes('/context/')) {
return 'context';
}

if (
entrypoint.endsWith('/directive.ts') ||
entrypoint.endsWith('/directive-helpers.ts') ||
Expand Down Expand Up @@ -225,6 +264,14 @@ export const lit2Config: ApiDocsConfig = {
// fine in practice, but when we add e.g. @lit/localize we'll need to be
// smarter here.
let [_, pkg, pathMinusExtension] = match;

if (pkg === 'labs/context') {
console.log(pkg, pathMinusExtension);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove

// There are no @lit-labs/context path extensions because everything is
// re-exported from root.
return '@lit-labs/context';
}

// TODO(aomarks) This wrongly assumes index.ts is always the package main.
return pathMinusExtension === 'index'
? pkg
Expand Down
45 changes: 25 additions & 20 deletions packages/lit-dev-tools-cjs/src/api-docs/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as fs from 'fs/promises';
import * as pathlib from 'path';
import {execFile} from 'child_process';
import {promisify} from 'util';
import {ApiDocsTransformer} from './transformer.js';
import {ApiDocsTransformer, Pages, SymbolMap} from './transformer.js';
import {lit2Config} from './configs/lit-2.js';

import type {ApiDocsConfig} from './types.js';
Expand Down Expand Up @@ -89,37 +89,42 @@ const analyze = async (config: ApiDocsConfig) => {
}

console.log(`Analyzing ${config.gitDir}`);
const app = new typedoc.Application();
app.options.addReader(new typedoc.TSConfigReader());
app.bootstrap({
tsconfig: config.tsConfigPath,
entryPoints: config.entrypointModules,
entryPointStrategy: typedoc.EntryPointStrategy.Expand,
});
const root = app.convert();
if (!root) {
throw new Error('TypeDoc.Application.convert() returned undefined');
}
const allPages: Pages = [];
const allSymbols: SymbolMap = {};
for (const pkg of config.packages) {
const app = new typedoc.Application();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At some point I thought I read some docs that typedoc had options for a monorepo, so you didn't need to make a new app for each package. I can't remember it though. This might matter for getting crosslinks between packages. Right now ReactiveElement say isn't a link in the context docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah - I need to investigate this further. I feel like I read that somewhere as well.

app.options.addReader(new typedoc.TSConfigReader());
app.bootstrap({
tsconfig: pkg.tsConfigPath,
entryPoints: pkg.entrypointModules,
});
const root = app.convert();
if (!root) {
throw new Error('TypeDoc.Application.convert() returned undefined');
}

const json = await app.serializer.projectToObject(
root,
pathlib.resolve(config.tsConfigPath, '..')
);
const transformer = new ApiDocsTransformer(json, config);
const {pages, symbolMap} = await transformer.transform();
const json = app.serializer.projectToObject(
root,
pathlib.resolve(pkg.tsConfigPath, '..')
);
const transformer = new ApiDocsTransformer(json, config);
const {pages, symbolMap} = await transformer.transform();
allPages.push(...pages);
Object.assign(allSymbols, symbolMap);
}

await fs.mkdir(pathlib.dirname(config.pagesOutPath), {recursive: true});
await fs.writeFile(
config.pagesOutPath,
JSON.stringify(pages, null, 2),
JSON.stringify(allPages, null, 2),
'utf8'
);
console.log(`Wrote ${config.pagesOutPath}`);

await fs.mkdir(pathlib.dirname(config.symbolsOutPath), {recursive: true});
await fs.writeFile(
config.symbolsOutPath,
JSON.stringify(symbolMap, null, 2),
JSON.stringify(allSymbols, null, 2),
'utf8'
);
console.log(`Wrote ${config.symbolsOutPath}`);
Expand Down
23 changes: 17 additions & 6 deletions packages/lit-dev-tools-cjs/src/api-docs/transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const symbolToExternalLink = new Map([
* Data consumed by lit.dev API docs Eleventy template. Each item is a separate
* page.
*/
type Pages = Array<{
export type Pages = Array<{
slug: string;
title: string;
items: Array<DeclarationReflection>;
Expand All @@ -76,7 +76,7 @@ type Pages = Array<{
* Map from $symbol to the location it appears in our docs. If there is more
* than one item, then the symbol is ambiguous.
*/
type SymbolMap = {
export type SymbolMap = {
[symbol: string]: Array<Location>;
};

Expand Down Expand Up @@ -120,6 +120,7 @@ export class ApiDocsTransformer {
// to copy our original entrypoint source info to each node.
(node as ExtendedDeclarationReflection).entrypointSources =
entrypoint.sources;
this.addKindStringToNodes(node);
for (const source of node.sources ?? []) {
this.makeSourceRelativeToMonorepoRoot(source);
await this.updateSourceFromDtsToTs(source);
Expand Down Expand Up @@ -579,9 +580,6 @@ export class ApiDocsTransformer {
const bEntrypoint =
(b as ExtendedDeclarationReflection).entrypointSources?.[0]?.fileName ??
'';
if (aEntrypoint !== bEntrypoint) {
return aEntrypoint.localeCompare(bEntrypoint);
}

// Hard-coded orderings
const idxA = findIndexOrInfinity(
Expand All @@ -594,10 +592,16 @@ export class ApiDocsTransformer {
(s) =>
s === (b as ExtendedDeclarationReflection).location?.anchor ?? b.name
);
if (idxA !== idxB) {

// Return an order if at least one of the symbols is hard coded.
if (idxA !== idxB && !(idxA === Infinity && idxB === Infinity)) {
return idxA - idxB;
}

if (aEntrypoint !== bEntrypoint) {
return aEntrypoint.localeCompare(bEntrypoint);
}

// Types after values
if (isType(a) && !isType(b)) {
return 1;
Expand Down Expand Up @@ -689,6 +693,13 @@ export class ApiDocsTransformer {
commentNode.summary = undefined;
}

private addKindStringToNodes(node: DeclarationReflection) {
if (node.kind) {
(node as ExtendedDeclarationReflection).kindString =
typedoc.ReflectionKind.singularString(node.kind);
}
}

/**
* TypeDoc 0.24.x removed `kindString` from their data structure. However we
* use `kindString` to locate and generate correct documentation within
Expand Down
46 changes: 27 additions & 19 deletions packages/lit-dev-tools-cjs/src/api-docs/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,30 @@ export interface Location {
excludeFromTOC?: boolean;
}

/**
* A package, such as `lit` or `@lit-labs/context`.
*/
export interface Package {
/**
* Path to the tsconfig.json that owns the entrypoint modules.
*/
tsConfigPath: string;

/**
* Entrypoint TypeScript modules for TypeDoc to analyze.
*
* The modules listed here should be the preferred modules that users should
* import from, because import statements will be generated using these
* entrypoints as the module specifier (e.g. `import {LitElement} from
* 'lit'`). GitHub source links will be generated pointing at the ultimate
* location where the symbol is concretely defined (e.g.
* `packages/lit-element/src/lit-element.ts`).
*
* If a directory, all .ts files within it are included.
*/
entrypointModules: Array<string>;
}

export interface ApiDocsConfig {
/**
* Git repo remote URL.
Expand All @@ -78,37 +102,20 @@ export interface ApiDocsConfig {
*/
gitDir: string;

/**
* Path to the tsconfig.json that owns the entrypoint modules.
*/
tsConfigPath: string;

/**
* The directory that TypeDoc chooses as the root of this package. Unclear why
* this is unpredictable.
*/
typedocRoot: string;

packages: Package[];

/**
* Extra setup/build commands to run after NPM install and before running
* TypeDoc.
*/
extraSetupCommands?: Array<{cmd: string; args: string[]}>;

/**
* Entrypoint TypeScript modules for TypeDoc to analyze.
*
* The modules listed here should be the preferred modules that users should
* import from, because import statements will be generated using these
* entrypoints as the module specifier (e.g. `import {LitElement} from
* 'lit'`). GitHub source links will be generated pointing at the ultimate
* location where the symbol is concretely defined (e.g.
* `packages/lit-element/src/lit-element.ts`).
*
* If a directory, all .ts files within it are included.
*/
entrypointModules: string[];

/**
* Where to write the API data that is consumed by our Eleventy template.
*/
Expand All @@ -134,6 +141,7 @@ export interface ApiDocsConfig {
title: string;
tocFilter?: (node: DeclarationReflection) => boolean;
versionLinks?: {[version: string]: string};
labs?: true;
}>;

/**
Expand Down