@render-policy/angular
v0.1.8
Published
Angular adapter for @render-policy/core: [rpRender] directive and <rp-markdown> component that render agent content without [innerHTML] or bypassSecurityTrustHtml; A2UI Text and Image components under @render-policy/angular/a2ui.
Maintainers
Readme
@render-policy/angular
Angular adapter for @render-policy/core: render agent content without [innerHTML]
or bypassSecurityTrustHtml().
import { provideRenderPolicy, RpMarkdownComponent, RpRenderDirective } from '@render-policy/angular';
bootstrapApplication(AppComponent, {
providers: [provideRenderPolicy({ mode: 'balanced', policy: { images: { hosts: ['cdn.example.com'] } } })],
});<div [rpRender]="message.content"></div>
<div [rpRender]="html" rpRenderMode="html"></div>
<div [rpRender]="message.content" [rpRenderStreaming]="message.pending"></div>
<rp-markdown [content]="message.content" [streaming]="message.pending" />RpRenderDirectiverenders into its host element on every change ofrpRender; withrpRenderStreamingtrue the growing text is rendered at most once per animation frame with incomplete URLs withheld, and when it turns false the final text is rendered once.RpMarkdownComponentis the same for Markdown, as an element withcontentandstreaminginputs.- Both are wrappers over
createContentBinding()from the core, so they behave exactly alike. RENDERERis the injectable renderer;RENDER_POLICY_CONFIGholds the options.- On the server (no
window) both insert plain text.
A2UI Text and Image
@render-policy/angular/a2ui is a secondary entry point with the basic catalog's Text and Image
for an A2UI v0.9 surface of your own. They take the values your renderer resolved (after data
binding and formatString) and run them through @render-policy/a2ui, an optional peer
dependency you install for this entry.
import { provideA2uiGuard, RpA2uiImageComponent, RpA2uiTextComponent } from '@render-policy/angular/a2ui';
bootstrapApplication(AppComponent, {
providers: [provideA2uiGuard({ policy: { images: { hosts: ['cdn.example.com'] } } })],
});<rp-a2ui-text [text]="text()" [variant]="props.variant" [componentId]="id" (decisions)="log($event)" />
<rp-a2ui-image [url]="url()" [description]="description()" [fit]="props.fit" [variant]="props.variant">image blocked</rp-a2ui-image><rp-a2ui-text>holdsTextto the catalog's contract (Markdown without HTML, images or links) and inserts a sanitized fragment into one element:h1–h5for headings, aspanforcaption, adivforbody. A bound value swapped later is rendered again through the same check.<rp-a2ui-image>checks the URL before an<img>exists: a blocked URL never reaches the DOM, so the browser makes no request, and the projected content renders instead.variantandfitcome from the agent: values outside the catalog's enums count as the defaults, so they never become a tag name or a class of the host page.A2UI_GUARDis the injectable guard;A2UI_GUARD_CONFIGholds the options.- On the server
<rp-a2ui-text>inserts plain text and<rp-a2ui-image>only its projected content.
Requires Angular 19 or later (signal inputs and effect()).
Build and publish:
npm run build -w packages/angular # ng-packagr, partial compilation, output in packages/angular/dist
cd packages/angular/dist && npm publish