@aglyn/plugins-mui 1.0.0-beta.215 → 1.0.0-beta.216
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.
- package/package.json +7 -7
- package/src/lib/components/collection-author-links.d.ts +41 -0
- package/src/lib/components/collection-author-links.js +135 -0
- package/src/lib/components/collection-author-links.js.map +1 -0
- package/src/lib/components/collection-author-profile.d.ts +67 -0
- package/src/lib/components/collection-author-profile.js +269 -0
- package/src/lib/components/collection-author-profile.js.map +1 -0
- package/src/lib/components/collection-categories.d.ts +52 -0
- package/src/lib/components/collection-categories.js +163 -0
- package/src/lib/components/collection-categories.js.map +1 -0
- package/src/lib/components/collection-common.d.ts +104 -0
- package/src/lib/components/collection-common.js +95 -0
- package/src/lib/components/collection-common.js.map +1 -0
- package/src/lib/components/collection-entries.d.ts +137 -0
- package/src/lib/components/collection-entries.js +358 -0
- package/src/lib/components/collection-entries.js.map +1 -0
- package/src/lib/components/collection-entry-author.d.ts +81 -0
- package/src/lib/components/collection-entry-author.js +259 -0
- package/src/lib/components/collection-entry-author.js.map +1 -0
- package/src/lib/components/collection-entry-body.d.ts +44 -0
- package/src/lib/components/collection-entry-body.js +328 -0
- package/src/lib/components/collection-entry-body.js.map +1 -0
- package/src/lib/components/collection-entry-meta.d.ts +88 -0
- package/src/lib/components/collection-entry-meta.js +331 -0
- package/src/lib/components/collection-entry-meta.js.map +1 -0
- package/src/lib/components/collection-presets.d.ts +18 -0
- package/src/lib/components/collection-presets.js +328 -0
- package/src/lib/components/collection-presets.js.map +1 -0
- package/src/lib/components/collection-related.d.ts +101 -0
- package/src/lib/components/collection-related.js +536 -0
- package/src/lib/components/collection-related.js.map +1 -0
- package/src/lib/components/collection-search-box.d.ts +92 -0
- package/src/lib/components/collection-search-box.js +334 -0
- package/src/lib/components/collection-search-box.js.map +1 -0
- package/src/lib/components/collection-search-fuse.d.ts +28 -0
- package/src/lib/components/collection-search-fuse.js +28 -0
- package/src/lib/components/collection-search-fuse.js.map +1 -0
- package/src/lib/components/collection-search.d.ts +62 -0
- package/src/lib/components/collection-search.js +140 -0
- package/src/lib/components/collection-search.js.map +1 -0
- package/src/lib/components/collection-share.d.ts +31 -0
- package/src/lib/components/collection-share.js +154 -0
- package/src/lib/components/collection-share.js.map +1 -0
- package/src/lib/components/collection.d.ts +19 -497
- package/src/lib/components/collection.js +19 -2982
- package/src/lib/components/collection.js.map +1 -1
- package/src/lib/components/image-list.d.ts +2 -2
- package/src/lib/components/image-list.js +4 -6
- package/src/lib/components/image-list.js.map +1 -1
- package/src/lib/element-tier.d.ts +9 -1
- package/src/lib/element-tier.js +12 -1
- package/src/lib/element-tier.js.map +1 -1
- package/src/lib/plugin.js +20 -12
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/utils/to-count.d.ts +25 -0
- package/src/lib/utils/to-count.js +30 -0
- package/src/lib/utils/to-count.js.map +1 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
/**
|
|
5
|
+
* @license
|
|
6
|
+
* Copyright 2026 Aglyn LLC
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
* you may not use this file except in compliance with the License.
|
|
10
|
+
* You may obtain a copy of the License at
|
|
11
|
+
*
|
|
12
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
*
|
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
* See the License for the specific language governing permissions and
|
|
18
|
+
* limitations under the License.
|
|
19
|
+
*/ import * as Aglyn from "@aglyn/aglyn";
|
|
20
|
+
import { mdiTextLong } from "@aglyn/shared-data-mdi";
|
|
21
|
+
import { AppLink } from "@aglyn/shared-ui-jsx";
|
|
22
|
+
import Box from "@mui/material/Box";
|
|
23
|
+
import MuiLink from "@mui/material/Link";
|
|
24
|
+
import Typography from "@mui/material/Typography";
|
|
25
|
+
import { forwardRef, useContext, useMemo } from "react";
|
|
26
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
27
|
+
import { UNRESOLVED_TOKEN } from "./collection-common.js";
|
|
28
|
+
// Persisted component id (AGL-551/582); the compose pipeline references it
|
|
29
|
+
// through the @aglyn/aglyn constant. Never rename.
|
|
30
|
+
export const ENTRY_BODY_ID = Aglyn.COLLECTION_ENTRY_BODY_COMPONENT_ID;
|
|
31
|
+
const renderInlines = (inlines, links)=>inlines.map((item, index)=>{
|
|
32
|
+
if (item.type === 'bold') return /*#__PURE__*/ _jsx("strong", {
|
|
33
|
+
children: item.text
|
|
34
|
+
}, index);
|
|
35
|
+
if (item.type === 'italic') return /*#__PURE__*/ _jsx("em", {
|
|
36
|
+
children: item.text
|
|
37
|
+
}, index);
|
|
38
|
+
if (item.type !== 'link') return /*#__PURE__*/ _jsx("span", {
|
|
39
|
+
children: item.text
|
|
40
|
+
}, index);
|
|
41
|
+
// Internal paths route through AppLink for client-side navigation
|
|
42
|
+
// (AGL-582); external links stay plain anchors. Editing surfaces render
|
|
43
|
+
// the link look without an href so clicks never navigate. A target named
|
|
44
|
+
// by REFERENCE resolves against the routing map first (AGL-3118), and one
|
|
45
|
+
// whose entry, listing or screen is gone renders as the words alone —
|
|
46
|
+
// never as an anchor holding the stored value.
|
|
47
|
+
const link = Aglyn.resolveMarkdownLink(item.href, links);
|
|
48
|
+
if (link.kind === 'text') return /*#__PURE__*/ _jsx("span", {
|
|
49
|
+
children: item.text
|
|
50
|
+
}, index);
|
|
51
|
+
if (link.kind === 'inert') {
|
|
52
|
+
return /*#__PURE__*/ _jsx(MuiLink, {
|
|
53
|
+
component: "span",
|
|
54
|
+
sx: {
|
|
55
|
+
cursor: 'default'
|
|
56
|
+
},
|
|
57
|
+
children: item.text
|
|
58
|
+
}, index);
|
|
59
|
+
}
|
|
60
|
+
return link.kind === 'internal' ? /*#__PURE__*/ _jsx(AppLink, {
|
|
61
|
+
href: link.href,
|
|
62
|
+
children: item.text
|
|
63
|
+
}, index) : /*#__PURE__*/ _jsx(MuiLink, {
|
|
64
|
+
href: link.href,
|
|
65
|
+
children: item.text
|
|
66
|
+
}, index);
|
|
67
|
+
});
|
|
68
|
+
/**
|
|
69
|
+
* Renders a content entry's markdown-lite body as themed MUI elements
|
|
70
|
+
* (AGL-551): headings, paragraphs, lists, and images pick up the site
|
|
71
|
+
* theme's typography instead of the old unthemed article HTML. Parsing is
|
|
72
|
+
* pure, so the full body server-renders (SEO keeps the article text).
|
|
73
|
+
*/ const CollectionEntryBody = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
74
|
+
// `intrinsicSizes` is destructured out rather than left in `rest`: `rest` is
|
|
75
|
+
// spread onto a Box, and a composition-stamped object would reach the DOM as
|
|
76
|
+
// an attribute React has no idea what to do with.
|
|
77
|
+
const { markdown, intrinsicSizes } = props, rest = _object_without_properties_loose(props, [
|
|
78
|
+
"markdown",
|
|
79
|
+
"intrinsicSizes"
|
|
80
|
+
]);
|
|
81
|
+
// Node styles ride the renderer-merged sx; recompose (stack.ts pattern).
|
|
82
|
+
const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [
|
|
83
|
+
props['sx']
|
|
84
|
+
];
|
|
85
|
+
// The routing map travels with the suppression flag: both decide what a
|
|
86
|
+
// link in this body renders as (AGL-3118).
|
|
87
|
+
const { suppressNavigation, screens } = useContext(Aglyn.ScreenLinkContext);
|
|
88
|
+
const links = useMemo(()=>({
|
|
89
|
+
suppressNavigation,
|
|
90
|
+
screens
|
|
91
|
+
}), [
|
|
92
|
+
suppressNavigation,
|
|
93
|
+
screens
|
|
94
|
+
]);
|
|
95
|
+
// The site being rendered, for image blocks (AGL-1686) — read once here
|
|
96
|
+
// because hooks cannot run inside the block map below.
|
|
97
|
+
const { hostId } = Aglyn.useSite();
|
|
98
|
+
const source = (markdown != null ? markdown : '').trim();
|
|
99
|
+
const unresolved = !source || UNRESOLVED_TOKEN.test(source);
|
|
100
|
+
const blocks = useMemo(()=>unresolved ? [] : Aglyn.parseMarkdownLite(source), [
|
|
101
|
+
source,
|
|
102
|
+
unresolved
|
|
103
|
+
]);
|
|
104
|
+
// Heading anchors, on the same terms as the Markdown element (AGL-1162).
|
|
105
|
+
// Without them a blog article could not carry an "On this page" aside at
|
|
106
|
+
// all: the Table of Contents element emits `#slug` links, and there was
|
|
107
|
+
// nothing on this page for them to land on.
|
|
108
|
+
const slugs = useMemo(()=>Aglyn.markdownHeadingSlugs(blocks), [
|
|
109
|
+
blocks
|
|
110
|
+
]);
|
|
111
|
+
if (unresolved) {
|
|
112
|
+
// Editing surfaces get an affordance; the published site renders
|
|
113
|
+
// nothing rather than a literal token.
|
|
114
|
+
if (!suppressNavigation) return /*#__PURE__*/ _jsx(Box, _extends({
|
|
115
|
+
ref: ref
|
|
116
|
+
}, rest));
|
|
117
|
+
return /*#__PURE__*/ _jsx(Box, _extends({
|
|
118
|
+
ref: ref
|
|
119
|
+
}, rest, {
|
|
120
|
+
sx: [
|
|
121
|
+
{
|
|
122
|
+
p: 2,
|
|
123
|
+
border: '1px dashed',
|
|
124
|
+
borderColor: 'divider',
|
|
125
|
+
color: 'text.secondary',
|
|
126
|
+
fontSize: 12,
|
|
127
|
+
fontFamily: 'system-ui, sans-serif'
|
|
128
|
+
},
|
|
129
|
+
...nodeSx
|
|
130
|
+
],
|
|
131
|
+
children: 'Entry body — the {{entry.body}} markdown renders here'
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
return /*#__PURE__*/ _jsx(Box, _extends({
|
|
135
|
+
ref: ref
|
|
136
|
+
}, rest, {
|
|
137
|
+
children: blocks.map((block, index)=>{
|
|
138
|
+
if (block.type === 'heading') {
|
|
139
|
+
return /*#__PURE__*/ _jsx(Typography, {
|
|
140
|
+
id: slugs[index],
|
|
141
|
+
variant: block.level === 2 ? 'h4' : 'h5',
|
|
142
|
+
component: block.level === 2 ? 'h2' : 'h3',
|
|
143
|
+
gutterBottom: true,
|
|
144
|
+
sx: {
|
|
145
|
+
scrollMarginTop: `${Aglyn.HEADING_ANCHOR_SCROLL_MARGIN}px`
|
|
146
|
+
},
|
|
147
|
+
children: renderInlines(block.inlines, links)
|
|
148
|
+
}, index);
|
|
149
|
+
}
|
|
150
|
+
if (block.type === 'image') {
|
|
151
|
+
return /*#__PURE__*/ _jsx(Box, _extends({
|
|
152
|
+
component: "img"
|
|
153
|
+
}, Aglyn.mediaBodyImageAttributes({
|
|
154
|
+
src: block.src,
|
|
155
|
+
hostId,
|
|
156
|
+
size: intrinsicSizes == null ? void 0 : intrinsicSizes[block.src]
|
|
157
|
+
}), {
|
|
158
|
+
alt: block.alt,
|
|
159
|
+
// Paired with the `width`/`height` above — see the Markdown
|
|
160
|
+
// element's copy of this: without it the height hint outlives
|
|
161
|
+
// the `maxWidth` cap and squashes the picture.
|
|
162
|
+
sx: {
|
|
163
|
+
maxWidth: '100%',
|
|
164
|
+
height: 'auto',
|
|
165
|
+
borderRadius: 1,
|
|
166
|
+
my: 1
|
|
167
|
+
}
|
|
168
|
+
}, Aglyn.DEFERRED_IMAGE_ATTRIBUTES), index);
|
|
169
|
+
}
|
|
170
|
+
if (block.type === 'list') {
|
|
171
|
+
return /*#__PURE__*/ _jsx(Box, {
|
|
172
|
+
component: "ul",
|
|
173
|
+
sx: {
|
|
174
|
+
lineHeight: 1.7,
|
|
175
|
+
pl: 3
|
|
176
|
+
},
|
|
177
|
+
children: block.items.map((item, itemIndex)=>/*#__PURE__*/ _jsx("li", {
|
|
178
|
+
children: renderInlines(item, links)
|
|
179
|
+
}, itemIndex))
|
|
180
|
+
}, index);
|
|
181
|
+
}
|
|
182
|
+
// A numbered list (AGL-1320) — a real `<ol>`, so the markers are the
|
|
183
|
+
// browser's and `start` survives: a notice that resumes at 7 has to
|
|
184
|
+
// read as 7 for the enumeration to mean anything.
|
|
185
|
+
if (block.type === 'orderedList') {
|
|
186
|
+
return /*#__PURE__*/ _jsx(Box, {
|
|
187
|
+
component: "ol",
|
|
188
|
+
start: block.start,
|
|
189
|
+
sx: {
|
|
190
|
+
lineHeight: 1.7,
|
|
191
|
+
pl: 3
|
|
192
|
+
},
|
|
193
|
+
children: block.items.map((item, itemIndex)=>/*#__PURE__*/ _jsx("li", {
|
|
194
|
+
children: renderInlines(item, links)
|
|
195
|
+
}, itemIndex))
|
|
196
|
+
}, index);
|
|
197
|
+
}
|
|
198
|
+
// Code blocks and tables (AGL-974). Both scroll rather than wrap:
|
|
199
|
+
// a wrapped code line or a squeezed table column loses the very
|
|
200
|
+
// structure that made the block worth writing.
|
|
201
|
+
if (block.type === 'code') {
|
|
202
|
+
return /*#__PURE__*/ _jsx(Box, {
|
|
203
|
+
component: "pre",
|
|
204
|
+
sx: {
|
|
205
|
+
my: 2,
|
|
206
|
+
p: 2,
|
|
207
|
+
overflowX: 'auto',
|
|
208
|
+
borderRadius: 1,
|
|
209
|
+
bgcolor: 'action.hover',
|
|
210
|
+
fontFamily: 'monospace',
|
|
211
|
+
fontSize: 14
|
|
212
|
+
},
|
|
213
|
+
children: /*#__PURE__*/ _jsx("code", {
|
|
214
|
+
children: block.text
|
|
215
|
+
})
|
|
216
|
+
}, index);
|
|
217
|
+
}
|
|
218
|
+
if (block.type === 'table') {
|
|
219
|
+
return /*#__PURE__*/ _jsx(Box, {
|
|
220
|
+
sx: {
|
|
221
|
+
my: 2,
|
|
222
|
+
overflowX: 'auto'
|
|
223
|
+
},
|
|
224
|
+
children: /*#__PURE__*/ _jsxs(Box, {
|
|
225
|
+
component: "table",
|
|
226
|
+
sx: {
|
|
227
|
+
borderCollapse: 'collapse',
|
|
228
|
+
width: '100%',
|
|
229
|
+
'& th, & td': {
|
|
230
|
+
border: '1px solid',
|
|
231
|
+
borderColor: 'divider',
|
|
232
|
+
px: 1.5,
|
|
233
|
+
py: 1
|
|
234
|
+
},
|
|
235
|
+
'& th': {
|
|
236
|
+
bgcolor: 'action.hover'
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
children: [
|
|
240
|
+
/*#__PURE__*/ _jsx("thead", {
|
|
241
|
+
children: /*#__PURE__*/ _jsx("tr", {
|
|
242
|
+
children: block.header.map((cell, cellIndex)=>{
|
|
243
|
+
var _block_align_cellIndex;
|
|
244
|
+
return /*#__PURE__*/ _jsx("th", {
|
|
245
|
+
style: {
|
|
246
|
+
textAlign: (_block_align_cellIndex = block.align[cellIndex]) != null ? _block_align_cellIndex : 'left'
|
|
247
|
+
},
|
|
248
|
+
children: renderInlines(cell, links)
|
|
249
|
+
}, cellIndex);
|
|
250
|
+
})
|
|
251
|
+
})
|
|
252
|
+
}),
|
|
253
|
+
/*#__PURE__*/ _jsx("tbody", {
|
|
254
|
+
children: block.rows.map((row, rowIndex)=>/*#__PURE__*/ _jsx("tr", {
|
|
255
|
+
children: row.map((cell, cellIndex)=>{
|
|
256
|
+
var _block_align_cellIndex;
|
|
257
|
+
return /*#__PURE__*/ _jsx("td", {
|
|
258
|
+
style: {
|
|
259
|
+
textAlign: (_block_align_cellIndex = block.align[cellIndex]) != null ? _block_align_cellIndex : 'left'
|
|
260
|
+
},
|
|
261
|
+
children: renderInlines(cell, links)
|
|
262
|
+
}, cellIndex);
|
|
263
|
+
})
|
|
264
|
+
}, rowIndex))
|
|
265
|
+
})
|
|
266
|
+
]
|
|
267
|
+
})
|
|
268
|
+
}, index);
|
|
269
|
+
}
|
|
270
|
+
// The article template's pull-quote (AGL-1315, Figma 170:225):
|
|
271
|
+
// larger italic prose behind a left accent. Palette tokens only, so
|
|
272
|
+
// it follows the site theme in both modes.
|
|
273
|
+
if (block.type === 'quote') {
|
|
274
|
+
return /*#__PURE__*/ _jsx(Typography, {
|
|
275
|
+
component: "blockquote",
|
|
276
|
+
sx: {
|
|
277
|
+
my: 3,
|
|
278
|
+
mx: 0,
|
|
279
|
+
pl: 2.5,
|
|
280
|
+
borderLeft: '3px solid',
|
|
281
|
+
borderColor: 'primary.main',
|
|
282
|
+
fontStyle: 'italic',
|
|
283
|
+
fontSize: '1.25em',
|
|
284
|
+
lineHeight: 1.6,
|
|
285
|
+
color: 'text.primary'
|
|
286
|
+
},
|
|
287
|
+
children: renderInlines(block.inlines, links)
|
|
288
|
+
}, index);
|
|
289
|
+
}
|
|
290
|
+
return /*#__PURE__*/ _jsx(Typography, {
|
|
291
|
+
variant: "body1",
|
|
292
|
+
sx: {
|
|
293
|
+
lineHeight: 1.7
|
|
294
|
+
},
|
|
295
|
+
gutterBottom: true,
|
|
296
|
+
children: renderInlines(block.inlines, links)
|
|
297
|
+
}, index);
|
|
298
|
+
})
|
|
299
|
+
}));
|
|
300
|
+
});
|
|
301
|
+
CollectionEntryBody.displayName = 'AglynCollectionEntryBody';
|
|
302
|
+
export const collectionEntryBodySchema = {
|
|
303
|
+
$id: ENTRY_BODY_ID,
|
|
304
|
+
pluginId: BUNDLE_ID,
|
|
305
|
+
displayName: 'Entry Body',
|
|
306
|
+
description: "The current entry's markdown body, on an entry template.",
|
|
307
|
+
category: Aglyn.ComponentCategory.TEXT,
|
|
308
|
+
icon: {
|
|
309
|
+
path: mdiTextLong.path,
|
|
310
|
+
sx: {
|
|
311
|
+
color: 'secondary.main'
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
flags: {
|
|
315
|
+
selfClosing: Aglyn.FEATURE_FLAG.ENABLED
|
|
316
|
+
},
|
|
317
|
+
attributes: [
|
|
318
|
+
{
|
|
319
|
+
name: 'markdown',
|
|
320
|
+
label: 'Markdown',
|
|
321
|
+
description: 'Markdown-lite content. Keep {{entry.body}} on entry-template ' + "screens so each entry's body renders here.",
|
|
322
|
+
component: Aglyn.FieldComponentType.TEXT_FIELD
|
|
323
|
+
}
|
|
324
|
+
]
|
|
325
|
+
};
|
|
326
|
+
export { CollectionEntryBody };
|
|
327
|
+
|
|
328
|
+
//# sourceMappingURL=collection-entry-body.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/mui/src/lib/components/collection-entry-body.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { mdiTextLong } from '@aglyn/shared-data-mdi'\nimport { AppLink } from '@aglyn/shared-ui-jsx'\nimport Box from '@mui/material/Box'\nimport MuiLink from '@mui/material/Link'\nimport Typography from '@mui/material/Typography'\nimport type { ReactNode } from 'react'\nimport { forwardRef, useContext, useMemo } from 'react'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { UNRESOLVED_TOKEN } from './collection-common'\n\n// Persisted component id (AGL-551/582); the compose pipeline references it\n// through the @aglyn/aglyn constant. Never rename.\nexport const ENTRY_BODY_ID: Aglyn.ComponentId =\n Aglyn.COLLECTION_ENTRY_BODY_COMPONENT_ID\n\nexport interface CollectionEntryBodyProps {\n /**\n * Markdown-lite source. On entry-template screens `{{entry.body}}`\n * resolves to the rendered entry's body at compose time.\n */\n markdown?: string\n /**\n * The pixel pair of each library image this body names, keyed by the target\n * as the body writes it, stamped by the composition from the assets' DAM\n * records (AGL-3149) — never set by hand, and never on the template, where\n * `markdown` is still the `{{entry.body}}` token and names no asset.\n */\n intrinsicSizes?: Record<string, { width: number; height: number }>\n}\n\nconst renderInlines = (\n inlines: Aglyn.MarkdownInline[],\n links: { suppressNavigation?: boolean; screens?: Aglyn.ScreenRouteMap },\n): ReactNode[] =>\n inlines.map((item, index) => {\n if (item.type === 'bold') return <strong key={index}>{item.text}</strong>\n if (item.type === 'italic') return <em key={index}>{item.text}</em>\n if (item.type !== 'link') return <span key={index}>{item.text}</span>\n // Internal paths route through AppLink for client-side navigation\n // (AGL-582); external links stay plain anchors. Editing surfaces render\n // the link look without an href so clicks never navigate. A target named\n // by REFERENCE resolves against the routing map first (AGL-3118), and one\n // whose entry, listing or screen is gone renders as the words alone —\n // never as an anchor holding the stored value.\n const link = Aglyn.resolveMarkdownLink(item.href, links)\n if (link.kind === 'text') return <span key={index}>{item.text}</span>\n if (link.kind === 'inert') {\n return (\n <MuiLink key={index} component=\"span\" sx={{ cursor: 'default' }}>\n {item.text}\n </MuiLink>\n )\n }\n return link.kind === 'internal' ? (\n <AppLink key={index} href={link.href}>\n {item.text}\n </AppLink>\n ) : (\n <MuiLink key={index} href={link.href}>\n {item.text}\n </MuiLink>\n )\n })\n\n/**\n * Renders a content entry's markdown-lite body as themed MUI elements\n * (AGL-551): headings, paragraphs, lists, and images pick up the site\n * theme's typography instead of the old unthemed article HTML. Parsing is\n * pure, so the full body server-renders (SEO keeps the article text).\n */\nconst CollectionEntryBody = forwardRef<\n HTMLDivElement,\n CollectionEntryBodyProps\n>((props, ref) => {\n // `intrinsicSizes` is destructured out rather than left in `rest`: `rest` is\n // spread onto a Box, and a composition-stamped object would reach the DOM as\n // an attribute React has no idea what to do with.\n const { markdown, intrinsicSizes, ...rest } = props\n // Node styles ride the renderer-merged sx; recompose (stack.ts pattern).\n const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [props['sx']]\n // The routing map travels with the suppression flag: both decide what a\n // link in this body renders as (AGL-3118).\n const { suppressNavigation, screens } = useContext(Aglyn.ScreenLinkContext)\n const links = useMemo(\n () => ({ suppressNavigation, screens }),\n [suppressNavigation, screens],\n )\n // The site being rendered, for image blocks (AGL-1686) — read once here\n // because hooks cannot run inside the block map below.\n const { hostId } = Aglyn.useSite()\n const source = (markdown ?? '').trim()\n const unresolved = !source || UNRESOLVED_TOKEN.test(source)\n const blocks = useMemo(\n () => (unresolved ? [] : Aglyn.parseMarkdownLite(source)),\n [source, unresolved],\n )\n // Heading anchors, on the same terms as the Markdown element (AGL-1162).\n // Without them a blog article could not carry an \"On this page\" aside at\n // all: the Table of Contents element emits `#slug` links, and there was\n // nothing on this page for them to land on.\n const slugs = useMemo(() => Aglyn.markdownHeadingSlugs(blocks), [blocks])\n if (unresolved) {\n // Editing surfaces get an affordance; the published site renders\n // nothing rather than a literal token.\n if (!suppressNavigation) return <Box ref={ref} {...rest} />\n return (\n <Box\n ref={ref}\n {...rest}\n sx={[\n {\n p: 2,\n border: '1px dashed',\n borderColor: 'divider',\n color: 'text.secondary',\n fontSize: 12,\n fontFamily: 'system-ui, sans-serif',\n },\n ...nodeSx,\n ]}\n >\n {'Entry body — the {{entry.body}} markdown renders here'}\n </Box>\n )\n }\n return (\n <Box ref={ref} {...rest}>\n {blocks.map((block, index) => {\n if (block.type === 'heading') {\n return (\n <Typography\n key={index}\n id={slugs[index]}\n variant={block.level === 2 ? 'h4' : 'h5'}\n component={block.level === 2 ? 'h2' : 'h3'}\n gutterBottom\n sx={{\n scrollMarginTop: `${Aglyn.HEADING_ANCHOR_SCROLL_MARGIN}px`,\n }}\n >\n {renderInlines(block.inlines, links)}\n </Typography>\n )\n }\n if (block.type === 'image') {\n return (\n <Box\n key={index}\n component=\"img\"\n // Resolved like the related cover image in collection-related.tsx\n // (AGL-1686): a body image is the same kind of asset and\n // has no reason to be stored in a more fragile form.\n //\n // And sized like one too, as of AGL-3149: the same call gives\n // the Markdown element's body images their candidate list and\n // intrinsic pair, so the two bodies cannot disagree about how a\n // picture in prose is delivered.\n {...Aglyn.mediaBodyImageAttributes({\n src: block.src,\n hostId,\n size: intrinsicSizes?.[block.src],\n })}\n alt={block.alt}\n // Paired with the `width`/`height` above — see the Markdown\n // element's copy of this: without it the height hint outlives\n // the `maxWidth` cap and squashes the picture.\n sx={{ maxWidth: '100%', height: 'auto', borderRadius: 1, my: 1 }}\n // An image inside an entry body is below the fold by\n // construction — the title, byline and opening paragraphs are\n // above it. This one carried no loading hint at all, so it was\n // fetched EAGERLY, at default priority, competing with the\n // entry's own cover (AGL-2486).\n {...Aglyn.DEFERRED_IMAGE_ATTRIBUTES}\n />\n )\n }\n if (block.type === 'list') {\n return (\n <Box key={index} component=\"ul\" sx={{ lineHeight: 1.7, pl: 3 }}>\n {block.items.map((item, itemIndex) => (\n <li key={itemIndex}>\n {renderInlines(item, links)}\n </li>\n ))}\n </Box>\n )\n }\n // A numbered list (AGL-1320) — a real `<ol>`, so the markers are the\n // browser's and `start` survives: a notice that resumes at 7 has to\n // read as 7 for the enumeration to mean anything.\n if (block.type === 'orderedList') {\n return (\n <Box\n key={index}\n component=\"ol\"\n start={block.start}\n sx={{ lineHeight: 1.7, pl: 3 }}\n >\n {block.items.map((item, itemIndex) => (\n <li key={itemIndex}>\n {renderInlines(item, links)}\n </li>\n ))}\n </Box>\n )\n }\n // Code blocks and tables (AGL-974). Both scroll rather than wrap:\n // a wrapped code line or a squeezed table column loses the very\n // structure that made the block worth writing.\n if (block.type === 'code') {\n return (\n <Box\n key={index}\n component=\"pre\"\n sx={{\n my: 2,\n p: 2,\n overflowX: 'auto',\n borderRadius: 1,\n bgcolor: 'action.hover',\n fontFamily: 'monospace',\n fontSize: 14,\n }}\n >\n <code>{block.text}</code>\n </Box>\n )\n }\n if (block.type === 'table') {\n return (\n <Box key={index} sx={{ my: 2, overflowX: 'auto' }}>\n <Box\n component=\"table\"\n sx={{\n borderCollapse: 'collapse',\n width: '100%',\n '& th, & td': {\n border: '1px solid',\n borderColor: 'divider',\n px: 1.5,\n py: 1,\n },\n '& th': { bgcolor: 'action.hover' },\n }}\n >\n <thead>\n <tr>\n {block.header.map((cell, cellIndex) => (\n <th\n key={cellIndex}\n style={{ textAlign: block.align[cellIndex] ?? 'left' }}\n >\n {renderInlines(cell, links)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {block.rows.map((row, rowIndex) => (\n <tr key={rowIndex}>\n {row.map((cell, cellIndex) => (\n <td\n key={cellIndex}\n style={{\n textAlign: block.align[cellIndex] ?? 'left',\n }}\n >\n {renderInlines(cell, links)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </Box>\n </Box>\n )\n }\n // The article template's pull-quote (AGL-1315, Figma 170:225):\n // larger italic prose behind a left accent. Palette tokens only, so\n // it follows the site theme in both modes.\n if (block.type === 'quote') {\n return (\n <Typography\n key={index}\n component=\"blockquote\"\n sx={{\n my: 3,\n mx: 0,\n pl: 2.5,\n borderLeft: '3px solid',\n borderColor: 'primary.main',\n fontStyle: 'italic',\n fontSize: '1.25em',\n lineHeight: 1.6,\n color: 'text.primary',\n }}\n >\n {renderInlines(block.inlines, links)}\n </Typography>\n )\n }\n return (\n <Typography\n key={index}\n variant=\"body1\"\n sx={{ lineHeight: 1.7 }}\n gutterBottom\n >\n {renderInlines(block.inlines, links)}\n </Typography>\n )\n })}\n </Box>\n )\n})\nCollectionEntryBody.displayName = 'AglynCollectionEntryBody'\n\nexport const collectionEntryBodySchema: Aglyn.ComponentSchema<CollectionEntryBodyProps> =\n {\n $id: ENTRY_BODY_ID,\n pluginId: BUNDLE_ID,\n displayName: 'Entry Body',\n description: \"The current entry's markdown body, on an entry template.\",\n category: Aglyn.ComponentCategory.TEXT,\n icon: { path: mdiTextLong.path, sx: { color: 'secondary.main' } },\n flags: { selfClosing: Aglyn.FEATURE_FLAG.ENABLED },\n attributes: [\n {\n name: 'markdown',\n label: 'Markdown',\n description:\n 'Markdown-lite content. Keep {{entry.body}} on entry-template ' +\n \"screens so each entry's body renders here.\",\n component: Aglyn.FieldComponentType.TEXT_FIELD,\n },\n ],\n }\n\nexport { CollectionEntryBody }\n"],"names":["Aglyn","mdiTextLong","AppLink","Box","MuiLink","Typography","forwardRef","useContext","useMemo","BUNDLE_ID","UNRESOLVED_TOKEN","ENTRY_BODY_ID","COLLECTION_ENTRY_BODY_COMPONENT_ID","renderInlines","inlines","links","map","item","index","type","strong","text","em","span","link","resolveMarkdownLink","href","kind","component","sx","cursor","CollectionEntryBody","props","ref","markdown","intrinsicSizes","rest","nodeSx","Array","isArray","suppressNavigation","screens","ScreenLinkContext","hostId","useSite","source","trim","unresolved","test","blocks","parseMarkdownLite","slugs","markdownHeadingSlugs","p","border","borderColor","color","fontSize","fontFamily","block","id","variant","level","gutterBottom","scrollMarginTop","HEADING_ANCHOR_SCROLL_MARGIN","mediaBodyImageAttributes","src","size","alt","maxWidth","height","borderRadius","my","DEFERRED_IMAGE_ATTRIBUTES","lineHeight","pl","items","itemIndex","li","start","overflowX","bgcolor","code","borderCollapse","width","px","py","thead","tr","header","cell","cellIndex","th","style","textAlign","align","tbody","rows","row","rowIndex","td","mx","borderLeft","fontStyle","displayName","collectionEntryBodySchema","$id","pluginId","description","category","ComponentCategory","TEXT","icon","path","flags","selfClosing","FEATURE_FLAG","ENABLED","attributes","name","label","FieldComponentType","TEXT_FIELD"],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import * as Aglyn from '@aglyn/aglyn';
|
|
18
|
+
import { type StackProps } from '@mui/material/Stack';
|
|
19
|
+
export declare const ENTRY_META_ID: Aglyn.ComponentId;
|
|
20
|
+
export interface CollectionEntryMetaProps extends StackProps {
|
|
21
|
+
/**
|
|
22
|
+
* Published date. Server-filled from the routed entry on entry templates
|
|
23
|
+
* (`expandCollectionEntryMeta`, AGL-1385); set it — or bind
|
|
24
|
+
* `{{entry.date}}` — only to override.
|
|
25
|
+
*/
|
|
26
|
+
date?: string;
|
|
27
|
+
/**
|
|
28
|
+
* How {@link date} reads when the server fills it in (AGL-1459) — a
|
|
29
|
+
* COMPOSE-TIME prop, like Related Posts' `limit`: it is answered where the
|
|
30
|
+
* timestamp still exists (`expandCollectionEntryMeta`) and never reaches the
|
|
31
|
+
* DOM. Blank, or `default`, is the locale date the block has always emitted.
|
|
32
|
+
*/
|
|
33
|
+
dateFormat?: Aglyn.CollectionEntryDateFormat;
|
|
34
|
+
/**
|
|
35
|
+
* Byline (AGL-1459). Server-filled from the entry's own author on entry
|
|
36
|
+
* templates, exactly like {@link date}; set it — or bind `{{entry.author}}`
|
|
37
|
+
* — only to override.
|
|
38
|
+
*/
|
|
39
|
+
author?: string;
|
|
40
|
+
/** Category; server-filled, or bind `{{entry.category}}` to override. */
|
|
41
|
+
category?: string;
|
|
42
|
+
/** Comma-joined tags; server-filled, or bind `{{entry.tags}}`. */
|
|
43
|
+
tags?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Round avatar shown before the byline (AGL-1459) — a media-picker target,
|
|
46
|
+
* so it holds a media reference (AGL-1215) as well as any URL form.
|
|
47
|
+
*
|
|
48
|
+
* A block-level pick, deliberately, and NOT a per-author image: entries
|
|
49
|
+
* carry an author NAME (`authorName`) and no portrait field, so a per-author
|
|
50
|
+
* avatar would need a schema decision on the entry model plus an editor
|
|
51
|
+
* field to fill it. Until then this is the site's brand mark, chosen once on
|
|
52
|
+
* the template — which is what the article frame actually asks for. Left
|
|
53
|
+
* unset it renders nothing at all, never a broken image.
|
|
54
|
+
*/
|
|
55
|
+
avatarImage?: string;
|
|
56
|
+
showDate?: boolean;
|
|
57
|
+
showAuthor?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Where the byline's NAME links — the author's page on this site
|
|
60
|
+
* (AGL-2519). Server-filled from the routed entry's author, like the
|
|
61
|
+
* avatar beside it; blank renders the name as plain text.
|
|
62
|
+
*
|
|
63
|
+
* Distinct from the author's own `url`, which the Entry Author card offers
|
|
64
|
+
* as a link row: this is "everything they wrote here", that is "their
|
|
65
|
+
* site", and a byline that conflated them would send a reader off-site from
|
|
66
|
+
* every article.
|
|
67
|
+
*/
|
|
68
|
+
authorPageUrl?: string;
|
|
69
|
+
/** Off leaves the byline as plain text even when the author has a page. */
|
|
70
|
+
linkAuthor?: boolean;
|
|
71
|
+
showCategory?: boolean;
|
|
72
|
+
showTags?: boolean;
|
|
73
|
+
showAvatar?: boolean;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* "{{entry.date}} · {{entry.category}}" meta line plus tag chips
|
|
77
|
+
* (AGL-582). Values arrive through entry tokens on entry renders; on other
|
|
78
|
+
* surfaces unresolved tokens collapse to nothing instead of leaking.
|
|
79
|
+
*
|
|
80
|
+
* On an entry template the tenant now also FILLS the three values from the
|
|
81
|
+
* routed entry when nothing is bound (`expandCollectionEntryMeta`, AGL-1385).
|
|
82
|
+
* Before that, a block dragged from the palette rather than dropped as the
|
|
83
|
+
* preset had no values at all — three "Show" switches gating nothing — and
|
|
84
|
+
* rendered as the empty `<Box>` below, at height 0.
|
|
85
|
+
*/
|
|
86
|
+
declare const CollectionEntryMeta: import("react").ForwardRefExoticComponent<Omit<CollectionEntryMetaProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
87
|
+
export declare const collectionEntryMetaSchema: Aglyn.ComponentSchema<CollectionEntryMetaProps>;
|
|
88
|
+
export { CollectionEntryMeta };
|