@dosgato/templating 0.0.85 → 0.0.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,7 +11,7 @@ import { APIClient } from './render.js';
11
11
  * During rendering, it will be "hydrated" - placed into a full page structure with its
12
12
  * parent and child components linked.
13
13
  */
14
- export declare abstract class Component<DataType extends ComponentData = any, FetchedType = any, RenderContextType extends ContextBase = any> extends ResourceProvider {
14
+ export declare abstract class Component<DataType extends ComponentData = any, FetchedType = any, RenderContextType extends ContextBase = ContextBase> extends ResourceProvider {
15
15
  /**
16
16
  * Provide this when you create a template to identify what you are defining.
17
17
  */
@@ -121,21 +121,55 @@ export declare abstract class Component<DataType extends ComponentData = any, Fe
121
121
  filter?: (c: T) => boolean;
122
122
  }): void;
123
123
  /**
124
- * The second phase of rendering a component is the context phase. This step is TOP-DOWN and
125
- * NON-MUTATING. Each component will receive the parent component's context and then pass a
126
- * NEW context object to its children.
124
+ * The second phase of rendering a component is the context phase. This step is TOP-DOWN.
125
+ * Each component will receive context from the parent component and then pass a new context
126
+ * object to its own children.
127
127
  *
128
128
  * This is useful for rendering logic that is sensitive to where the component exists in
129
129
  * the hierarchy of the page. For instance, if a parent component has used an h2 header
130
130
  * already, it will want to inform its children so that they can use h3 next, and they inform
131
131
  * their children that h4 is next, and so on. (Header level tracking is supported by default in
132
- * dosgato CMS.)
132
+ * dosgato CMS - see printHeader() and advanceHeader())
133
133
  *
134
134
  * This function may return a promise in case you need to do something asynchronous based on
135
135
  * the context received from the parent, but use it sparingly since it will stall the process.
136
136
  * Try to do all asynchronous work in the fetch phase.
137
137
  */
138
- setContext(renderCtxFromParent: RenderContextType): RenderContextType | Promise<RenderContextType>;
138
+ setContext(renderCtxFromParent: RenderContextType, areaName: string): RenderContextType | Promise<RenderContextType>;
139
+ /**
140
+ * This function will be provided by the rendering server and should be used inside your fetch
141
+ * method to prepare editor-provided HTML for later rendering. It will do things like find and
142
+ * resolve link definitions in the internal dosgato format.
143
+ */
144
+ fetchRichText: (text: string) => Promise<void>;
145
+ /**
146
+ * This function will be provided by the rendering server and should be used during the render
147
+ * phase to clean up editor-provided HTML. It will do things like clean up tags that were accidentally
148
+ * left open to protect overall page integrity, and fix header levels for accessibility.
149
+ *
150
+ * For instance, an editor supplies a title to be placed above some rich editor content. The
151
+ * title uses an <h2>, so the headers inside the rich editor content should start at <h3> and
152
+ * should not use <h1> or <h2>.
153
+ *
154
+ * Setting headerLevel: 3 instructs the renderRichText function to analyze and rebalance the header
155
+ * structure of the content so that if it had an h2, it woud be replaced with an h3. Additionally,
156
+ * if the user skipped a header level (a WCAG violation) that situation will be repaired as well
157
+ * as possible.
158
+ *
159
+ * If you do not provide a headerLevel, the one from `this.renderCtx` will be used. However, if you
160
+ * provide a non-blank value for `advanceHeader`, the headerLevel from `this.renderCtx` + 1 will be used.
161
+ *
162
+ * This way you can easily render a piece of rich text in a component that has an optional title:
163
+ *
164
+ * this.renderRichText(this.data.richtext, { advanceHeader: this.data.title })
165
+ *
166
+ * If this.data.title is non-blank, the rich text will be balanced below it, but if it is blank,
167
+ * it will be balanced at the level the title would have had.
168
+ */
169
+ renderRichText: (html: string, opts?: {
170
+ headerLevel?: number;
171
+ advanceHeader?: string | undefined | null;
172
+ }) => string;
139
173
  /**
140
174
  * The final phase of rendering a component is the render phase. This step is BOTTOM-UP -
141
175
  * components at the bottom of the hierarchy will be rendered first, and the result of the
@@ -239,7 +273,7 @@ export declare abstract class Component<DataType extends ComponentData = any, Fe
239
273
  static editBar: (path: string, opts: EditBarOpts) => string;
240
274
  static newBar: (path: string, opts: NewBarOpts) => string;
241
275
  constructor(data: DataType, path: string, parent: Component | undefined, editMode: boolean);
242
- areas: Map<string, Component<any, any, any>[]>;
276
+ areas: Map<string, Component<any, any, ContextBase>[]>;
243
277
  data: Omit<DataType, 'areas'>;
244
278
  fetched: FetchedType;
245
279
  renderCtx: RenderContextType;
@@ -306,6 +340,7 @@ export interface ContextBase {
306
340
  * This way every page will have a perfect header tree and avoid complaints from WAVE.
307
341
  */
308
342
  headerLevel: number;
343
+ [keys: string]: any;
309
344
  }
310
345
  interface BarOpts {
311
346
  editMode?: boolean;
package/dist/component.js CHANGED
@@ -73,21 +73,21 @@ export class Component extends ResourceProvider {
73
73
  this.registerInherited(areaName, components, page.id, opts?.mode);
74
74
  }
75
75
  /**
76
- * The second phase of rendering a component is the context phase. This step is TOP-DOWN and
77
- * NON-MUTATING. Each component will receive the parent component's context and then pass a
78
- * NEW context object to its children.
76
+ * The second phase of rendering a component is the context phase. This step is TOP-DOWN.
77
+ * Each component will receive context from the parent component and then pass a new context
78
+ * object to its own children.
79
79
  *
80
80
  * This is useful for rendering logic that is sensitive to where the component exists in
81
81
  * the hierarchy of the page. For instance, if a parent component has used an h2 header
82
82
  * already, it will want to inform its children so that they can use h3 next, and they inform
83
83
  * their children that h4 is next, and so on. (Header level tracking is supported by default in
84
- * dosgato CMS.)
84
+ * dosgato CMS - see printHeader() and advanceHeader())
85
85
  *
86
86
  * This function may return a promise in case you need to do something asynchronous based on
87
87
  * the context received from the parent, but use it sparingly since it will stall the process.
88
88
  * Try to do all asynchronous work in the fetch phase.
89
89
  */
90
- setContext(renderCtxFromParent) {
90
+ setContext(renderCtxFromParent, areaName) {
91
91
  return renderCtxFromParent;
92
92
  }
93
93
  /**
package/dist/render.d.ts CHANGED
@@ -1,9 +1,7 @@
1
1
  import { ContextBase, DataData, PageData, PageRecord, PageRecordOptionalData } from './component.js';
2
2
  import { AssetLink, DataFolderLink, DataLink, LinkDefinition, PageLink } from './links.js';
3
3
  export declare function printHeader(ctx: ContextBase, content: string | undefined | null, attributes?: Record<string, string>): string;
4
- export declare function advanceHeader(ctx: ContextBase, content: string | undefined | null): {
5
- headerLevel: number;
6
- };
4
+ export declare function advanceHeader<T extends ContextBase>(ctx: T, content: string | undefined | null): T;
7
5
  export interface PictureResize {
8
6
  /** the width of this particular resize */
9
7
  width: number;
@@ -88,13 +86,6 @@ export interface APIClient {
88
86
  absolute?: boolean;
89
87
  extension?: string;
90
88
  }) => string;
91
- /**
92
- * This function will be provided by the rendering server and should be used inside your fetch
93
- * method to prepare editor-provided HTML for rendering. It will do things like find and resolve
94
- * link definitions in the internal dosgato format and clean up tags that were accidentally left
95
- * open to protect overall page integrity.
96
- */
97
- processRich: (text: string) => Promise<string>;
98
89
  /**
99
90
  * This function will retrieve information about an image to help you construct responsive HTML
100
91
  * for a <picture> element including the <img> and all <source> tags.
package/dist/render.js CHANGED
@@ -1,9 +1,9 @@
1
- import { htmlEncode, isBlank } from 'txstate-utils';
1
+ import { htmlEncode, isBlank, isNotEmpty } from 'txstate-utils';
2
2
  export function printHeader(ctx, content, attributes) {
3
3
  if (isBlank(content))
4
4
  return '';
5
- const level = (ctx.headerLevel ?? 0) + 1;
6
- const attr = attributes ? ' ' + Object.entries(attributes).map(([key, val]) => `${key}="${htmlEncode(val)}"`).join(' ') : '';
5
+ const level = ctx.headerLevel ?? 1;
6
+ const attr = isNotEmpty(attributes) ? ' ' + Object.entries(attributes).map(([key, val]) => `${key}="${htmlEncode(val)}"`).join(' ') : '';
7
7
  if (level < 1)
8
8
  return `<h1${attr}>${content}</h1>`;
9
9
  if (level > 6)
@@ -11,8 +11,7 @@ export function printHeader(ctx, content, attributes) {
11
11
  return `<h${level}${attr}>${content}</h${level}>`;
12
12
  }
13
13
  export function advanceHeader(ctx, content) {
14
- const ret = { ...ctx };
15
14
  if (!isBlank(content))
16
- ret.headerLevel = (ret.headerLevel ?? 0) + 1;
17
- return ret;
15
+ ctx.headerLevel = (ctx.headerLevel ?? 1) + 1;
16
+ return ctx;
18
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosgato/templating",
3
- "version": "0.0.85",
3
+ "version": "0.0.87",
4
4
  "description": "A library to support building templates for dosgato CMS.",
5
5
  "type": "module",
6
6
  "exports": {