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

chore: add api extractor to FAST SSR #5939

Merged
Merged
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
9 changes: 9 additions & 0 deletions packages/web-components/fast-ssr/api-extractor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"extends": "../../../api-extractor.json",
"mainEntryPointFilePath": "./dist/dts/exports.d.ts",
"dtsRollup": {
"enabled": true,
"betaTrimmedFilePath": "./dist/fast-ssr.d.ts"
}
}
62 changes: 62 additions & 0 deletions packages/web-components/fast-ssr/docs/api-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
## API Report File for "@microsoft/fast-ssr"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

import { Binding } from '@microsoft/fast-element';
import { ComposableStyles } from '@microsoft/fast-element';
import { Constructable } from '@microsoft/fast-element';
import { ElementRenderer } from '@lit-labs/ssr';
import { ExecutionContext } from '@microsoft/fast-element';
import { FASTElement } from '@microsoft/fast-element';
import { RenderInfo } from '@lit-labs/ssr';
import { ViewBehaviorFactory } from '@microsoft/fast-element';
import { ViewTemplate } from '@microsoft/fast-element';

// @beta
export type ComponentDOMEmissionMode = "shadow";

// @beta
export abstract class FASTElementRenderer extends ElementRenderer {
constructor(tagName: string);
attributeChangedCallback(name: string, old: string | null, value: string | null): void;
connectedCallback(): void;
readonly element: FASTElement;
static matchesClass(ctor: typeof HTMLElement): boolean;
renderLight(renderInfo: RenderInfo): IterableIterator<string>;
renderShadow(renderInfo: RenderInfo): IterableIterator<string>;
protected abstract styleRenderer: StyleRenderer;
protected abstract templateRenderer: TemplateRenderer;
}

// @beta
function fastSSR(): {
templateRenderer: TemplateRenderer;
elementRenderer: typeof FASTElementRenderer;
defaultRenderInfo: RenderInfo;
};
export default fastSSR;

// @beta
export interface StyleRenderer {
render(styles: ComposableStyles): string;
}

// @beta
export class TemplateRenderer {
readonly componentDOMEmissionMode: ComponentDOMEmissionMode;
render(template: ViewTemplate | string, renderInfo: RenderInfo, source?: unknown, context?: ExecutionContext): IterableIterator<string>;
// Warning: (ae-forgotten-export) The symbol "Op" needs to be exported by the entry point exports.d.ts
//
// @internal
renderOpCodes(codes: Op[], renderInfo: RenderInfo, source: unknown, context: ExecutionContext): IterableIterator<string>;
// Warning: (ae-forgotten-export) The symbol "ViewBehaviorFactoryRenderer" needs to be exported by the entry point exports.d.ts
//
// @internal
withViewBehaviorFactoryRenderers(...renderers: ViewBehaviorFactoryRenderer<any>[]): void;
}

// (No @packageDocumentation comment for this package)

```
12 changes: 9 additions & 3 deletions packages/web-components/fast-ssr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
},
"scripts": {
"clean": "tsc -b --clean src",
"build": "tsc -b src",
"build": "tsc -b src && yarn doc",
"doc": "api-extractor run --local",
"doc:ci": "api-extractor run",
"prepare": "yarn run clean && yarn run build",
"build-server": "tsc -b server",
"eslint": "eslint . --ext .ts",
Expand All @@ -31,9 +33,12 @@
},
"description": "A package for rendering FAST components outside the browser.",
"main": "./dist/esm/exports.js",
"types": "./dist/dts/exports.d.ts",
"types": "./dist/fast-ssr.d.ts",
"exports": {
"." : "./dist/esm/exports.js",
"." : {
"default": "./dist/esm/exports.js",
"types": "./dist/fast-ssr.d.ts"
},
"./install-dom-shim": "./dist/esm/dom-shim.js"
},
"private": true,
Expand All @@ -44,6 +49,7 @@
"tslib": "^2.4.0"
},
"devDependencies": {
"@microsoft/api-extractor": "7.23.1",
"@playwright/test": "^1.20.1",
"@types/express": "^4.17.13",
"@types/node": "^17.0.17",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ test.describe("FASTElementRenderer", () => {
const result = consolidate(templateRenderer.render(html`<styled-element></styled-element>`, defaultRenderInfo));
expect(result).toBe("<styled-element><template shadowroot=\"open\"><style>:host { display: block; }</style><style>:host { color: red; }</style></template></styled-element>");
});
test(`should render stylesheets as 'fast-style' elements when configured`, () => {
const { templateRenderer, defaultRenderInfo} = fastSSR({useFASTStyle: true});
test.skip(`should render stylesheets as 'fast-style' elements when configured`, () => {
const { templateRenderer, defaultRenderInfo} = fastSSR(/* Replace w/ configuration when fast-style work is complete{useFASTStyle: true}*/);
const result = consolidate(templateRenderer.render(html`<styled-element></styled-element>`, defaultRenderInfo));
expect(result).toBe(`<styled-element><template shadowroot=\"open\"><fast-style style-id="fast-style-0" css=":host { display: block; }\"></fast-style><fast-style style-id=\"fast-style-1\" css=\":host { color: red; }"></fast-style></template></styled-element>`);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import { TemplateRenderer } from "../template-renderer/template-renderer.js";
import { SSRView } from "../view.js";
import { FASTSSRStyleStrategy } from "./style-strategy.js";

/**
* An {@link @lit-labs/ssr#ElementRenderer} implementation designed to render components
* built with FAST.
*
* @beta
*/
export abstract class FASTElementRenderer extends ElementRenderer {
/**
* The element instance represented by the {@link FASTElementRenderer}.
Expand Down
30 changes: 14 additions & 16 deletions packages/web-components/fast-ssr/src/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,14 @@ import {
} from "@microsoft/fast-element";
import { FASTElementRenderer } from "./element-renderer/element-renderer.js";
import { FASTSSRStyleStrategy } from "./element-renderer/style-strategy.js";
import {
FASTStyleStyleRenderer,
StyleElementStyleRenderer,
StyleRenderer,
} from "./styles/style-renderer.js";
import { StyleElementStyleRenderer, StyleRenderer } from "./styles/style-renderer.js";
import { defaultViewBehaviorFactoryRenderers } from "./template-renderer/directives.js";
import {
ComponentDOMEmissionMode,
TemplateRenderer,
TemplateRendererConfiguration,
} from "./template-renderer/template-renderer.js";
import { SSRView } from "./view.js";

export type Configuration = TemplateRendererConfiguration;
Compiler.setDefaultStrategy(
(
html: string | HTMLTemplateElement,
Expand All @@ -40,8 +35,6 @@ DOM.setUpdateMode(false);

/**
* Factory for creating SSR rendering assets.
* @param config - FAST SSR configuration
*
* @example
* ```ts
* import "@microsoft/install-dom-shim";
Expand All @@ -51,20 +44,18 @@ DOM.setUpdateMode(false);
*
* const streamableSSRResult = templateRenderer.render(html`...`, defaultRenderInfo);
* ```
*
* @beta
*/
export default function (
config?: Configuration
): {
export default function fastSSR(): {
templateRenderer: TemplateRenderer;
elementRenderer: typeof FASTElementRenderer;
defaultRenderInfo: RenderInfo;
} {
const templateRenderer = new TemplateRenderer(config);
const templateRenderer = new TemplateRenderer();
const elementRenderer = class extends FASTElementRenderer {
protected templateRenderer: TemplateRenderer = templateRenderer;
protected styleRenderer: StyleRenderer = config?.useFASTStyle
? new FASTStyleStyleRenderer()
: new StyleElementStyleRenderer();
protected styleRenderer = new StyleElementStyleRenderer();
};

templateRenderer.withViewBehaviorFactoryRenderers(
Expand All @@ -81,3 +72,10 @@ export default function (
},
};
}

export type {
TemplateRenderer,
FASTElementRenderer,
StyleRenderer,
ComponentDOMEmissionMode,
};
10 changes: 9 additions & 1 deletion packages/web-components/fast-ssr/src/styles/style-renderer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ComposableStyles, ElementStyles } from "@microsoft/fast-element";
import { ComposableStyles } from "@microsoft/fast-element";
import { fastStyleTagName } from "./fast-style.js";
function collectStyles(style: ComposableStyles): string {
let content: string = "";
Expand All @@ -19,7 +19,15 @@ function collectStyles(style: ComposableStyles): string {
return content;
}

/**
* A renderer for {@link @microsoft/fast-element#ComposableStyles}
* @beta
*/
export interface StyleRenderer {
/**
* Renders composable styles to a string.
* @param styles - The styles to render.
*/
render(styles: ComposableStyles): string;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ test.describe("TemplateRenderer", () => {
});
});

test.describe("should allow configuration", () => {
test.describe.skip("should allow configuration", () => {
test("that emits to light DOM", () => {
const instance = new TemplateRenderer({componentDOMEmissionMode: "light"});
expect(instance.componentDOMEmissionMode).toBe("light")
const instance = new TemplateRenderer(/* Re-implement w/ light mode emission is finished {componentDOMEmissionMode: "light"} */);
expect(instance.componentDOMEmissionMode).toBe("light");
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,32 @@ function getLast<T>(arr: T[]): T | undefined {
return arr[arr.length - 1];
}

export type ComponentDOMEmissionMode = "shadow" | "light";
export interface TemplateRendererConfiguration {
/**
* Controls whether the template renderer should emit component template code to the component's shadow DOM or to its light DOM.
* @default "shadow"
*/
componentDOMEmissionMode?: ComponentDOMEmissionMode;

/**
* Controls whether the template renderer should emit FASTStyle elements for stylesheets.
* Using FASTStyle can help reduce the SSR payload by only emitting stylesheet content once,
* and leveraging a Custom Element to map those stylesheets back to FAST element's on the client.
* @default false
*/
useFASTStyle?: boolean;
}

export class TemplateRenderer
implements Readonly<Required<TemplateRendererConfiguration>> {
/**
* The mode for which a component's internals should be rendered.
* @beta
*/
export type ComponentDOMEmissionMode = "shadow";

/**
* A class designed to render HTML templates. The renderer supports
* rendering {@link @microsoft/fast-element#ViewTemplate} instances as well
* as arbitrary HTML strings.
*
* @beta
*/
export class TemplateRenderer {
private viewBehaviorFactoryRenderers: Map<
any,
ViewBehaviorFactoryRenderer<any>
> = new Map();

/**
* {@inheritDoc TemplateRendererConfiguration.componentDOMEmissionMode}
* Controls how the {@link TemplateRenderer} will emit component DOM internals.
*/
public readonly componentDOMEmissionMode: ComponentDOMEmissionMode = "shadow";

/** {@inheritdoc TemplateRendererConfiguration.useFASTStyle} */
public readonly useFASTStyle: boolean = false;
constructor(config?: TemplateRendererConfiguration) {
if (config) {
Object.assign(this, config);
}
}

/**
*
* Renders a {@link @microsoft/fast-element#ViewTemplate} or HTML string.
* @param template - The template to render.
* @param renderInfo - Information about the rendering context.
* @param source - Any source data to render the template and evaluate bindings with.
Expand All @@ -76,10 +64,11 @@ export class TemplateRenderer

/**
* Render a set of op codes.
* @param codes - the op codes to render.
* @param renderInfo - renderInfo context.
* @param source - source data.
*
* @internal
* @param codes
* @param renderInfo
* @param source
*/
public *renderOpCodes(
codes: Op[],
Expand All @@ -95,10 +84,15 @@ export class TemplateRenderer
case OpType.viewBehaviorFactory: {
const factory = code.factory as ViewBehaviorFactory & Aspected;
const ctor = factory.constructor;
if (this.viewBehaviorFactoryRenderers.has(ctor)) {
yield* this.viewBehaviorFactoryRenderers
.get(ctor)!
.render(factory, renderInfo, source, this, context);
const renderer = this.viewBehaviorFactoryRenderers.get(ctor);
if (renderer) {
yield* renderer.render(
factory,
renderInfo,
source,
this,
context
);
} else if (factory.aspectType && factory.binding) {
const result = factory.binding(source, context);

Expand Down Expand Up @@ -231,6 +225,8 @@ export class TemplateRenderer
/**
* Registers DirectiveRenderers to use when rendering templates.
* @param renderers - The directive renderers to register
*
* @internal
*/
public withViewBehaviorFactoryRenderers(
...renderers: ViewBehaviorFactoryRenderer<any>[]
Expand All @@ -254,8 +250,8 @@ export class TemplateRenderer

/**
* Format attribute key/value pair into a HTML attribute string.
* @param name
* @param value
* @param name - the attribute name.
* @param value - the attribute value.
*/
private static formatAttribute(name: string, value: string) {
return value === "" ? name : `${name}="${value}"`;
Expand Down
18 changes: 18 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3518,6 +3518,24 @@
source-map "~0.6.1"
typescript "~4.6.3"

"@microsoft/[email protected]":
version "7.23.1"
resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.23.1.tgz#483e339cc73669c709ff215a76eb0e6d9a31de5b"
integrity sha512-J5cTjbMzSZPRZT4AKvFI1KmLGHVhV6bHnFcPo3Og9cN9QmknzpKg5BxvpBecEdFKNZxUpUrBkps2xOQ4Fjc6zg==
dependencies:
"@microsoft/api-extractor-model" "7.17.2"
"@microsoft/tsdoc" "0.14.1"
"@microsoft/tsdoc-config" "~0.16.1"
"@rushstack/node-core-library" "3.45.4"
"@rushstack/rig-package" "0.3.11"
"@rushstack/ts-command-line" "4.10.10"
colors "~1.2.1"
lodash "~4.17.15"
resolve "~1.17.0"
semver "~7.3.0"
source-map "~0.6.1"
typescript "~4.6.3"

"@microsoft/fast-components-class-name-contracts-base@^4.8.0":
version "4.8.0"
resolved "https://registry.yarnpkg.com/@microsoft/fast-components-class-name-contracts-base/-/fast-components-class-name-contracts-base-4.8.0.tgz#e59c85fd7ff88865d2c5bd6a8cf287232c1469f7"
Expand Down