@dosgato/templating 0.0.39 → 0.0.40

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.
@@ -1,4 +1,3 @@
1
- import { EditBarOpts } from './editbar.js';
2
1
  import { ResourceProvider } from './provider.js';
3
2
  import { APIClient } from './render.js';
4
3
  /**
@@ -9,8 +8,15 @@ import { APIClient } from './render.js';
9
8
  * parent and child components linked.
10
9
  */
11
10
  export declare abstract class Component<DataType extends ComponentData = any, FetchedType = any, RenderContextType extends ContextBase = any> extends ResourceProvider {
11
+ /**
12
+ * Provide this when you create a template to identify what you are defining.
13
+ */
12
14
  static templateKey: string;
13
- static templateName: string;
15
+ /**
16
+ * These functions will be provided by the rendering server
17
+ */
18
+ static editBar: (path: string, opts: EditBarOpts) => string;
19
+ static newBar: (path: string, opts: EditBarOpts) => string;
14
20
  areas: Map<string, Component<any, any, any>[]>;
15
21
  data: Omit<DataType, 'areas'>;
16
22
  fetched: FetchedType;
@@ -19,6 +25,20 @@ export declare abstract class Component<DataType extends ComponentData = any, Fe
19
25
  parent?: Component;
20
26
  page?: Page;
21
27
  hadError: boolean;
28
+ autoLabel: () => string;
29
+ autoNewLabel: () => string;
30
+ /**
31
+ * When hydrating an inherited component, the renderer will set this to the id of the page it
32
+ * came from. You may use this information in any of the phases to alter your behavior if needed.
33
+ *
34
+ * For instance, you may decide that your fetch function needs some extra information from the
35
+ * originating page instead of the page you're being inherited into (your `this.page` will
36
+ * be the page currently being rendered, NOT the page the inheritable component came from).
37
+ *
38
+ * This property is also used to alter the edit bar. Inherited components may never be edited
39
+ * except on their original page, so the edit bar will render with a link to the original page.
40
+ */
41
+ inheritedFrom?: string;
22
42
  /**
23
43
  * This property will be set during page render and you may refer to it at any time to
24
44
  * determine whether you are doing your work in edit mode or regular rendering mode.
@@ -55,6 +75,13 @@ export declare abstract class Component<DataType extends ComponentData = any, Fe
55
75
  * other Component instances.
56
76
  */
57
77
  getAncestorPageData: () => Promise<PageData[]>;
78
+ /**
79
+ * Some components may be inheritable to subpages within the same site. For instance, a site's
80
+ * social media links may appear on every page's footer. To accomplish this in your template,
81
+ * you need to fetch the data in your fetch phase and then call this function within your fetch
82
+ * to let the renderer know it needs to hydrate them and include them in the render.
83
+ */
84
+ registerInherited: (area: string, components: ComponentData[], top?: true) => void;
58
85
  /**
59
86
  * The first phase of rendering a component is the fetch phase. Each component may
60
87
  * provide a fetch method that looks up data it needs from external sources. This step
@@ -92,7 +119,7 @@ export declare abstract class Component<DataType extends ComponentData = any, Fe
92
119
  * render will be passed to parent components so that the HTML can be included during the
93
120
  * render of the parent component.
94
121
  */
95
- abstract render(renderedAreas: Map<string, string[]>): string;
122
+ abstract render(renderedAreas: Map<string, RenderedComponent[]>): string;
96
123
  /**
97
124
  * Sometimes pages are requested with an alternate extension like .rss or .ics. In these
98
125
  * situations, each component should consider whether it should output anything. For
@@ -114,6 +141,9 @@ export declare abstract class Component<DataType extends ComponentData = any, Fe
114
141
  */
115
142
  logError(e: Error): void;
116
143
  protected passError(e: Error, path: string): void;
144
+ renderComponents(components?: RenderedComponent[], opts?: {
145
+ hideInheritBars?: boolean;
146
+ }): string;
117
147
  /**
118
148
  * During rendering, each component should determine the CSS blocks that it needs. This may
119
149
  * change depending on the data. For instance, if you need some CSS to style up an image, but
@@ -130,11 +160,11 @@ export declare abstract class Component<DataType extends ComponentData = any, Fe
130
160
  jsBlocks(): string[];
131
161
  /**
132
162
  * Components may override this function to give their edit bars a custom
133
- * label instead of using the templateName property
163
+ * label instead of using the template name
134
164
  *
135
165
  * For instance, you could return this.data.title
136
166
  */
137
- editLabel(): string;
167
+ editLabel(): undefined;
138
168
  /**
139
169
  * Components may override this function to give their edit bars a custom
140
170
  * CSS class
@@ -147,7 +177,7 @@ export declare abstract class Component<DataType extends ComponentData = any, Fe
147
177
  * For instance, an area that only accepts 'layout' components could
148
178
  * return "Add Layout"
149
179
  */
150
- newLabel(areaName: string): string;
180
+ newLabel(areaName: string): undefined;
151
181
  /**
152
182
  * Components may override this function to give their new bars a custom
153
183
  * CSS class
@@ -195,6 +225,17 @@ export interface ContextBase {
195
225
  */
196
226
  headerLevel: number;
197
227
  }
228
+ export interface EditBarOpts {
229
+ extraClass?: string;
230
+ label?: string;
231
+ editMode?: boolean;
232
+ inheritedFrom?: string;
233
+ }
234
+ export interface RenderedComponent {
235
+ inherited: boolean;
236
+ html: string;
237
+ editbar: string;
238
+ }
198
239
  export declare abstract class Page<DataType extends PageData = any, FetchedType = any, RenderContextType extends ContextBase = any> extends Component<DataType, FetchedType, RenderContextType> {
199
240
  pagePath: string;
200
241
  /**
package/dist/component.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { isNotBlank } from 'txstate-utils';
2
- import { editBar, newBar } from './editbar.js';
3
2
  import { ResourceProvider } from './provider.js';
4
3
  /**
5
4
  * This is the primary templating class to build your templates. Subclass it and provide
@@ -92,6 +91,11 @@ export class Component extends ResourceProvider {
92
91
  passError(e, path) {
93
92
  this.parent?.passError(e, path);
94
93
  }
94
+ // helper function to help you print an area, but you can also override this if you
95
+ // need to do something advanced like wrap each component in a div
96
+ renderComponents(components = [], opts) {
97
+ return components.flatMap(c => c.inherited && opts?.hideInheritBars ? [c.html] : [c.editbar, c.html]).join('');
98
+ }
95
99
  /**
96
100
  * During rendering, each component should determine the CSS blocks that it needs. This may
97
101
  * change depending on the data. For instance, if you need some CSS to style up an image, but
@@ -112,13 +116,12 @@ export class Component extends ResourceProvider {
112
116
  }
113
117
  /**
114
118
  * Components may override this function to give their edit bars a custom
115
- * label instead of using the templateName property
119
+ * label instead of using the template name
116
120
  *
117
121
  * For instance, you could return this.data.title
118
122
  */
119
123
  editLabel() {
120
- const This = this.constructor;
121
- return This.templateName;
124
+ return undefined;
122
125
  }
123
126
  /**
124
127
  * Components may override this function to give their edit bars a custom
@@ -135,7 +138,7 @@ export class Component extends ResourceProvider {
135
138
  * return "Add Layout"
136
139
  */
137
140
  newLabel(areaName) {
138
- return 'Add Content';
141
+ return undefined;
139
142
  }
140
143
  /**
141
144
  * Components may override this function to give their new bars a custom
@@ -150,10 +153,11 @@ export class Component extends ResourceProvider {
150
153
  * Generally should not be overridden - override editLabel and editClass instead
151
154
  */
152
155
  editBar(opts = {}) {
153
- opts.label ?? (opts.label = this.editLabel());
156
+ opts.label ?? (opts.label = this.editLabel() ?? this.autoLabel());
154
157
  opts.extraClass ?? (opts.extraClass = this.editClass());
155
- opts.editMode = this.editMode;
156
- return editBar(this.path, opts);
158
+ opts.editMode ?? (opts.editMode = this.editMode);
159
+ opts.inheritedFrom ?? (opts.inheritedFrom = this.inheritedFrom);
160
+ return Component.editBar(this.path, opts);
157
161
  }
158
162
  /**
159
163
  * Components may override this function to provide a custom new bar
@@ -161,10 +165,11 @@ export class Component extends ResourceProvider {
161
165
  * Generally should not be overridden - override newLabel and newClass instead
162
166
  */
163
167
  newBar(areaName, opts = {}) {
164
- opts.label ?? (opts.label = this.newLabel(areaName));
168
+ opts.label ?? (opts.label = this.newLabel(areaName) ?? this.autoNewLabel());
165
169
  opts.extraClass ?? (opts.extraClass = this.newClass(areaName));
166
- opts.editMode = this.editMode;
167
- return newBar([this.path, 'areas', areaName].filter(isNotBlank).join('.'), opts);
170
+ opts.editMode ?? (opts.editMode = this.editMode);
171
+ opts.inheritedFrom ?? (opts.inheritedFrom = this.inheritedFrom);
172
+ return Component.newBar([this.path, 'areas', areaName].filter(isNotBlank).join('.'), opts);
168
173
  }
169
174
  }
170
175
  export class Page extends Component {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosgato/templating",
3
- "version": "0.0.39",
3
+ "version": "0.0.40",
4
4
  "description": "A library to support building templates for dosgato CMS.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -18,7 +18,7 @@
18
18
  "txstate-utils": "^1.7.1"
19
19
  },
20
20
  "devDependencies": {
21
- "eslint-config-standard-with-typescript": "^21.0.1",
21
+ "eslint-config-standard-with-typescript": "^22.0.0",
22
22
  "typescript": "^4.4.2"
23
23
  },
24
24
  "repository": {
package/dist/editbar.d.ts DELETED
@@ -1,11 +0,0 @@
1
- export interface EditBarOpts {
2
- extraClass?: string;
3
- label?: string;
4
- editMode?: boolean;
5
- }
6
- export declare function editBar(path: string, opts: EditBarOpts & {
7
- label: string;
8
- }): string;
9
- export declare function newBar(path: string, opts: EditBarOpts & {
10
- label: string;
11
- }): string;
package/dist/editbar.js DELETED
@@ -1,23 +0,0 @@
1
- import { htmlEncode, randomid } from 'txstate-utils';
2
- export function editBar(path, opts) {
3
- if (!opts.editMode)
4
- return '';
5
- const id = randomid();
6
- return `
7
- <div class="dg-edit-bar ${opts.extraClass ?? ''}" data-path="${htmlEncode(path)}" draggable="true" ondragstart="window.dgEditing.drag(event)" ondragover="window.dgEditing.over(event)" ondragend="window.dgEditing.drop(event)">
8
- <span id="${id}" class="dg-edit-bar-label">${htmlEncode(opts.label)}</span>
9
- <button onclick="window.dgEditing.edit(event)" aria-describedby="${id}">Edit</button>
10
- <button onclick="window.dgEditing.move(event)" aria-describedby="${id}">Move</button>
11
- <button onclick="window.dgEditing.del(event)" aria-describedby="${id}">Trash</button>
12
- </div>
13
- `.trim();
14
- }
15
- export function newBar(path, opts) {
16
- if (!opts.editMode)
17
- return '';
18
- return `
19
- <div role="button" onclick="window.dgEditing.create(event)" class="dg-new-bar ${opts.extraClass ?? ''}" data-path="${htmlEncode(path)}">
20
- ${htmlEncode(opts.label)}
21
- </div>
22
- `.trim();
23
- }