@aglyn/plugins-ai 1.0.0-beta.244 → 1.0.0-beta.246
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 +17 -17
- package/src/lib/activity/ai-activity-actions.js +3 -1
- package/src/lib/activity/ai-activity-actions.js.map +1 -1
- package/src/lib/components/ai-job-links.js +7 -0
- package/src/lib/components/ai-job-links.js.map +1 -1
- package/src/lib/components/ai-product-zones.d.ts +3 -1
- package/src/lib/components/ai-product-zones.js.map +1 -1
- package/src/lib/components/ai-products-hub-card.component.js +1 -1
- package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
- package/src/lib/components/ai-products-proposals.component.js +17 -9
- package/src/lib/components/ai-products-proposals.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.js +6 -4
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-upsell-dialog.component.js +1 -1
- package/src/lib/components/ai-upsell-dialog.component.js.map +1 -1
- package/src/lib/jobs/ai-build-capabilities.js +162 -2
- package/src/lib/jobs/ai-build-capabilities.js.map +1 -1
- package/src/lib/jobs/ai-job-build-step.d.ts +7 -0
- package/src/lib/jobs/ai-job-build-step.js +85 -16
- package/src/lib/jobs/ai-job-build-step.js.map +1 -1
- package/src/lib/jobs/ai-job-duplicate-step.d.ts +123 -0
- package/src/lib/jobs/ai-job-duplicate-step.js +269 -0
- package/src/lib/jobs/ai-job-duplicate-step.js.map +1 -0
- package/src/lib/jobs/ai-job-layout-language.js +13 -0
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
- package/src/lib/jobs/ai-job-navigation-step.d.ts +157 -0
- package/src/lib/jobs/ai-job-navigation-step.js +439 -0
- package/src/lib/jobs/ai-job-navigation-step.js.map +1 -0
- package/src/lib/jobs/ai-job-page-language.d.ts +2 -1
- package/src/lib/jobs/ai-job-page-language.js +21 -5
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-sections.js +1 -1
- package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +4 -2
- package/src/lib/jobs/ai-job-plan-step.js +16 -7
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-products-step.d.ts +2 -2
- package/src/lib/jobs/ai-job-products-step.js +2 -2
- package/src/lib/jobs/ai-job-products-step.js.map +1 -1
- package/src/lib/jobs/ai-job-settings-step.d.ts +272 -0
- package/src/lib/jobs/ai-job-settings-step.js +695 -0
- package/src/lib/jobs/ai-job-settings-step.js.map +1 -0
- package/src/lib/jobs/ai-job-site-content.d.ts +20 -6
- package/src/lib/jobs/ai-job-site-content.js +28 -12
- package/src/lib/jobs/ai-job-site-content.js.map +1 -1
- package/src/lib/jobs/ai-job-site-datasets.d.ts +2 -0
- package/src/lib/jobs/ai-job-site-datasets.js +10 -3
- package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.d.ts +3 -1
- package/src/lib/jobs/ai-job-site-step.js +70 -10
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-site-publish.d.ts +62 -4
- package/src/lib/jobs/ai-site-publish.js +203 -56
- package/src/lib/jobs/ai-site-publish.js.map +1 -1
- package/src/lib/layout-language/ai-layout-compiler.d.ts +7 -4
- package/src/lib/layout-language/ai-layout-compiler.js +26 -25
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame-hollows.d.ts +41 -0
- package/src/lib/layout-language/ai-layout-frame-hollows.js +330 -0
- package/src/lib/layout-language/ai-layout-frame-hollows.js.map +1 -0
- package/src/lib/layout-language/ai-layout-frame.d.ts +18 -1
- package/src/lib/layout-language/ai-layout-frame.js +83 -13
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-listings.d.ts +35 -0
- package/src/lib/layout-language/ai-layout-listings.js +34 -0
- package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
- package/src/lib/layout-language/ai-layout-tree.d.ts +2 -0
- package/src/lib/layout-language/ai-layout-tree.js +17 -0
- package/src/lib/layout-language/ai-layout-tree.js.map +1 -1
- package/src/lib/model/ai-build-job.d.ts +23 -0
- package/src/lib/model/ai-build-job.js +102 -13
- package/src/lib/model/ai-build-job.js.map +1 -1
- package/src/lib/model/ai-build-plan.d.ts +25 -0
- package/src/lib/model/ai-build-plan.js +45 -1
- package/src/lib/model/ai-build-plan.js.map +1 -1
- package/src/lib/model/ai-credit-estimate.d.ts +52 -0
- package/src/lib/model/ai-credit-estimate.js +51 -0
- package/src/lib/model/ai-credit-estimate.js.map +1 -1
- package/src/lib/model/ai-job-activity.js +4 -1
- package/src/lib/model/ai-job-activity.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +10 -2
- package/src/lib/model/ai-jobs.types.js +4 -1
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-layout-menus.d.ts +104 -0
- package/src/lib/model/ai-layout-menus.js +518 -0
- package/src/lib/model/ai-layout-menus.js.map +1 -0
- package/src/lib/model/ai-products.d.ts +31 -1
- package/src/lib/model/ai-products.js +34 -1
- package/src/lib/model/ai-products.js.map +1 -1
- package/src/lib/model/ai-site-inventory.d.ts +15 -0
- package/src/lib/model/ai-site-inventory.js.map +1 -1
- package/src/lib/model/ai-site-job.d.ts +10 -0
- package/src/lib/model/ai-site-job.js +36 -9
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-store-pages.js +1 -1
- package/src/lib/model/ai-site-store-pages.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +53 -0
- package/src/lib/runtime/ai-doctrine-validators.js +166 -25
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +7 -2
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-palette.generated.js +1 -1
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/runtime/ai-products-generation.d.ts +4 -2
- package/src/lib/runtime/ai-products-generation.js +12 -6
- package/src/lib/runtime/ai-products-generation.js.map +1 -1
- package/src/lib/runtime/site-inventory.d.ts +12 -0
- package/src/lib/runtime/site-inventory.js +29 -1
- package/src/lib/runtime/site-inventory.js.map +1 -1
- package/src/lib/server.js +12 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/testing/stand-in-dataset-index.js +37 -3
- package/src/lib/testing/stand-in-dataset-index.js.map +1 -1
- package/src/lib/tools/ai-products-tool.d.ts +3 -1
- package/src/lib/tools/ai-products-tool.js +15 -5
- package/src/lib/tools/ai-products-tool.js.map +1 -1
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2026 Aglyn LLC
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/ /**
|
|
18
|
+
* A SITE'S MENUS, CHANGED BY CODE (AGL-3728).
|
|
19
|
+
*
|
|
20
|
+
* A site's header and footer menus are not a separate document: they are the
|
|
21
|
+
* Besigner's own elements in the layout's node tree — Page Links
|
|
22
|
+
* (`muiScreenLink`) in a list in the header, the same list again in the phone
|
|
23
|
+
* menu's Drawer, Dropdown Menus (`muiNavMenu`, `muiMegaMenu`) holding more
|
|
24
|
+
* Page Links, and the footer's list of Page Links. That is what a person
|
|
25
|
+
* edits in the Besigner, and what this edits, so a menu the AI changed opens
|
|
26
|
+
* in the editor exactly as one a person changed.
|
|
27
|
+
*
|
|
28
|
+
* A change is planned as words — add "About", take "Blog" out, call
|
|
29
|
+
* "Services" "What we do", link "Shop" to a page, put "Contact" last — and
|
|
30
|
+
* applied here, in code, to every list of the menu it names:
|
|
31
|
+
*
|
|
32
|
+
* - THE HEADER's lists are the lists of links inside its App Bar (or an
|
|
33
|
+
* element that renders `header`): the bar's own row and the phone menu's.
|
|
34
|
+
* Where it has lists that render `nav`, only those are its menu, so the
|
|
35
|
+
* brand and an account link beside it never are. Failing any list, a
|
|
36
|
+
* Toolbar holding a link (the brand's counts), else the first Toolbar.
|
|
37
|
+
* The brand (a link the compiler named `brand`) is never a menu item, and
|
|
38
|
+
* an item added beside nothing but the brand goes after it.
|
|
39
|
+
* - THE FOOTER's list is the longest list of links inside the element that
|
|
40
|
+
* renders `footer`.
|
|
41
|
+
*
|
|
42
|
+
* Recognized the way a store's links are added to a layout
|
|
43
|
+
* (`aiLayoutWithStoreLinks`, AGL-3676). A layout with no list for a menu is
|
|
44
|
+
* left as it is, and the change says what to do by hand.
|
|
45
|
+
*
|
|
46
|
+
* A new link copies a link already in the list it joins — its look, and in
|
|
47
|
+
* the phone menu the interaction that closes it — so it looks like its
|
|
48
|
+
* neighbours. A link added under a parent ("Services > Roofing") goes into the
|
|
49
|
+
* Dropdown Menu of that name in a bar's row, made where there is none (the
|
|
50
|
+
* link of that name, if any, becoming its first entry); a phone menu and a
|
|
51
|
+
* footer have no dropdowns, so there it joins the list after its parent.
|
|
52
|
+
*
|
|
53
|
+
* ONE implementation for every menu change the AI makes (AGL-3747): the
|
|
54
|
+
* `navigation` op's (`ai-job-navigation-step.ts`), and the header entries a
|
|
55
|
+
* guided site start adds to its layout when it publishes
|
|
56
|
+
* (`aiLayoutWithNavigation` in `ai-site-publish.ts`), including the /blog
|
|
57
|
+
* entry a retried posts part puts back.
|
|
58
|
+
*
|
|
59
|
+
* Pure: nodes in, nodes out.
|
|
60
|
+
*/ import { aiLayoutRepairFrameHollows } from "../layout-language/ai-layout-frame-hollows.js";
|
|
61
|
+
export const AI_MENU_NAMES = [
|
|
62
|
+
'header',
|
|
63
|
+
'footer'
|
|
64
|
+
];
|
|
65
|
+
const LINK = 'muiScreenLink';
|
|
66
|
+
/** The Besigner's Dropdown Menu and Mega Menu: a labelled item holding links. Persisted ids. */ export const AI_MENU_DROPDOWNS = [
|
|
67
|
+
'muiNavMenu',
|
|
68
|
+
'muiMegaMenu'
|
|
69
|
+
];
|
|
70
|
+
const NAV_MENU = 'muiNavMenu';
|
|
71
|
+
const DRAWER = 'muiDrawer';
|
|
72
|
+
/** The most items a menu may be asked to change in one go. */ export const AI_MENU_CHANGES_MAX = 12;
|
|
73
|
+
/** The longest label a menu item takes. */ export const AI_MENU_LABEL_MAX = 40;
|
|
74
|
+
const renders = (node, element)=>{
|
|
75
|
+
var _node_props, _node_props1;
|
|
76
|
+
return ((_node_props = node.props) == null ? void 0 : _node_props['element']) === element || ((_node_props1 = node.props) == null ? void 0 : _node_props1['component']) === element || node.componentId === element;
|
|
77
|
+
};
|
|
78
|
+
const said = (value)=>typeof value === 'string' ? value.replace(/\s+/g, ' ').trim() : '';
|
|
79
|
+
const same = (a, b)=>a.trim().toLowerCase() === b.trim().toLowerCase();
|
|
80
|
+
/** Where a menu change says an entry lives, in words: `Roofing`, `Services › Roofing`. */ export function aiMenuEntryName(entry) {
|
|
81
|
+
return entry.parent ? `${entry.parent} › ${entry.label}` : entry.label;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The layout's nodes with a navigation change made to the menus named
|
|
85
|
+
* (AGL-3728). Each menu's lists all take the same change, so the bar and the
|
|
86
|
+
* phone menu never disagree. `newId` mints a node id; the default is a
|
|
87
|
+
* counter under `ai_nav_`.
|
|
88
|
+
*/ export function aiLayoutWithMenuChanges(nodes, menus, changes, options = {}) {
|
|
89
|
+
var _options_newId;
|
|
90
|
+
const map = {};
|
|
91
|
+
for (const [id, raw] of Object.entries(nodes)){
|
|
92
|
+
if (!raw || typeof raw !== 'object') continue;
|
|
93
|
+
map[id] = _extends({}, raw, {
|
|
94
|
+
$id: typeof raw.$id === 'string' && raw.$id ? raw.$id : id
|
|
95
|
+
}, raw.props ? {
|
|
96
|
+
props: _extends({}, raw.props)
|
|
97
|
+
} : {}, raw.nodes ? {
|
|
98
|
+
nodes: [
|
|
99
|
+
...raw.nodes
|
|
100
|
+
]
|
|
101
|
+
} : {});
|
|
102
|
+
}
|
|
103
|
+
let counter = 0;
|
|
104
|
+
const newId = (_options_newId = options.newId) != null ? _options_newId : ()=>{
|
|
105
|
+
counter += 1;
|
|
106
|
+
while(map[`ai_nav_${counter}`])counter += 1;
|
|
107
|
+
return `ai_nav_${counter}`;
|
|
108
|
+
};
|
|
109
|
+
const all = Object.values(map);
|
|
110
|
+
const under = (roots)=>{
|
|
111
|
+
const seen = new Set();
|
|
112
|
+
const queue = roots.map((root)=>root.$id);
|
|
113
|
+
while(queue.length){
|
|
114
|
+
var _map_id_nodes;
|
|
115
|
+
const id = queue.shift();
|
|
116
|
+
if (seen.has(id) || !map[id]) continue;
|
|
117
|
+
seen.add(id);
|
|
118
|
+
queue.push(...(_map_id_nodes = map[id].nodes) != null ? _map_id_nodes : []);
|
|
119
|
+
}
|
|
120
|
+
return seen;
|
|
121
|
+
};
|
|
122
|
+
const isBrand = (id)=>/brand/i.test(id);
|
|
123
|
+
const isLink = (id)=>{
|
|
124
|
+
var _map_id;
|
|
125
|
+
return ((_map_id = map[id]) == null ? void 0 : _map_id.componentId) === LINK && !isBrand(id);
|
|
126
|
+
};
|
|
127
|
+
const isDropdown = (id)=>{
|
|
128
|
+
var _map_id;
|
|
129
|
+
return AI_MENU_DROPDOWNS.includes(String((_map_id = map[id]) == null ? void 0 : _map_id.componentId));
|
|
130
|
+
};
|
|
131
|
+
const isItem = (id)=>isLink(id) || isDropdown(id);
|
|
132
|
+
const itemsOf = (list)=>{
|
|
133
|
+
var _list_nodes;
|
|
134
|
+
return ((_list_nodes = list.nodes) != null ? _list_nodes : []).filter(isItem);
|
|
135
|
+
};
|
|
136
|
+
const labelOf = (id)=>{
|
|
137
|
+
var _map_id_props, _map_id, _map_id_props1, _map_id1;
|
|
138
|
+
return said(isDropdown(id) ? (_map_id = map[id]) == null ? void 0 : (_map_id_props = _map_id.props) == null ? void 0 : _map_id_props['label'] : (_map_id1 = map[id]) == null ? void 0 : (_map_id_props1 = _map_id1.props) == null ? void 0 : _map_id_props1['children']);
|
|
139
|
+
};
|
|
140
|
+
// ── The lists each menu is ───────────────────────────────────────────
|
|
141
|
+
const listsOf = (menu)=>{
|
|
142
|
+
var _toolbars_find;
|
|
143
|
+
if (menu === 'footer') {
|
|
144
|
+
const ids = under(all.filter((node)=>renders(node, 'footer')));
|
|
145
|
+
const longest = [
|
|
146
|
+
...ids
|
|
147
|
+
].map((id)=>map[id]).filter((node)=>{
|
|
148
|
+
var _node_nodes;
|
|
149
|
+
return ((_node_nodes = node.nodes) != null ? _node_nodes : []).filter(isLink).length >= 2;
|
|
150
|
+
}).sort((a, b)=>{
|
|
151
|
+
var _b_nodes, _a_nodes;
|
|
152
|
+
return ((_b_nodes = b.nodes) != null ? _b_nodes : []).filter(isLink).length - ((_a_nodes = a.nodes) != null ? _a_nodes : []).filter(isLink).length;
|
|
153
|
+
})[0];
|
|
154
|
+
return longest ? [
|
|
155
|
+
longest
|
|
156
|
+
] : [];
|
|
157
|
+
}
|
|
158
|
+
const ids = under(all.filter((node)=>node.componentId === 'muiAppBar' || renders(node, 'header')));
|
|
159
|
+
const lists = [
|
|
160
|
+
...ids
|
|
161
|
+
].map((id)=>map[id]).filter((node)=>itemsOf(node).length >= 2);
|
|
162
|
+
const landmarks = lists.filter((node)=>renders(node, 'nav'));
|
|
163
|
+
if (landmarks.length) return landmarks;
|
|
164
|
+
if (lists.length) return lists;
|
|
165
|
+
// A bar's Toolbar holding a link, the brand's included (a starter's
|
|
166
|
+
// header is a brand and a search), else its first Toolbar.
|
|
167
|
+
const toolbars = all.filter((node)=>node.componentId === 'muiToolbar');
|
|
168
|
+
const toolbar = (_toolbars_find = toolbars.find((node)=>{
|
|
169
|
+
var _node_nodes;
|
|
170
|
+
return ((_node_nodes = node.nodes) != null ? _node_nodes : []).some((id)=>{
|
|
171
|
+
var _map_id;
|
|
172
|
+
return ((_map_id = map[id]) == null ? void 0 : _map_id.componentId) === LINK;
|
|
173
|
+
});
|
|
174
|
+
})) != null ? _toolbars_find : toolbars[0];
|
|
175
|
+
return toolbar ? [
|
|
176
|
+
toolbar
|
|
177
|
+
] : [];
|
|
178
|
+
};
|
|
179
|
+
// A phone menu (in a Drawer) and a footer hold no dropdowns: their entries stay flat.
|
|
180
|
+
const drawerIds = under(all.filter((node)=>node.componentId === DRAWER));
|
|
181
|
+
const flat = (menu, list)=>menu === 'footer' || drawerIds.has(list.$id);
|
|
182
|
+
const found = {};
|
|
183
|
+
const notDone = new Set();
|
|
184
|
+
// What each entry came to across a menu's lists: done where any list did it.
|
|
185
|
+
const outcomes = new Map();
|
|
186
|
+
const mark = (key, ok, done, failed)=>{
|
|
187
|
+
var _ref;
|
|
188
|
+
const was = outcomes.get(key);
|
|
189
|
+
outcomes.set(key, {
|
|
190
|
+
ok: ok || ((_ref = was == null ? void 0 : was.ok) != null ? _ref : false),
|
|
191
|
+
done,
|
|
192
|
+
failed: was && !was.ok && !ok ? was.failed : failed
|
|
193
|
+
});
|
|
194
|
+
};
|
|
195
|
+
let changed = false;
|
|
196
|
+
const removeTree = (id)=>{
|
|
197
|
+
var _ref;
|
|
198
|
+
var _map_id;
|
|
199
|
+
for (const child of [
|
|
200
|
+
...(_ref = (_map_id = map[id]) == null ? void 0 : _map_id.nodes) != null ? _ref : []
|
|
201
|
+
])removeTree(child);
|
|
202
|
+
delete map[id];
|
|
203
|
+
};
|
|
204
|
+
const detach = (id)=>{
|
|
205
|
+
for (const node of Object.values(map)){
|
|
206
|
+
var _node_nodes;
|
|
207
|
+
if ((_node_nodes = node.nodes) == null ? void 0 : _node_nodes.includes(id)) node.nodes = node.nodes.filter((child)=>child !== id);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
const setTarget = (node, to)=>{
|
|
211
|
+
var _node_props;
|
|
212
|
+
const props = _extends({}, (_node_props = node.props) != null ? _node_props : {});
|
|
213
|
+
delete props['screenId'];
|
|
214
|
+
delete props['href'];
|
|
215
|
+
node.props = _extends({}, props, to);
|
|
216
|
+
};
|
|
217
|
+
/** A new link like the list's own, else a plain one. */ const linkLike = (template, parentId, label, to)=>{
|
|
218
|
+
var _ref;
|
|
219
|
+
const id = newId();
|
|
220
|
+
const props = (template == null ? void 0 : template.props) ? _extends({}, template.props) : {
|
|
221
|
+
renderAs: 'link',
|
|
222
|
+
color: 'inherit'
|
|
223
|
+
};
|
|
224
|
+
delete props['screenId'];
|
|
225
|
+
delete props['href'];
|
|
226
|
+
map[id] = _extends({}, template != null ? template : {
|
|
227
|
+
sx: {
|
|
228
|
+
textDecoration: 'none',
|
|
229
|
+
whiteSpace: 'nowrap'
|
|
230
|
+
}
|
|
231
|
+
}, {
|
|
232
|
+
$id: id,
|
|
233
|
+
componentId: LINK,
|
|
234
|
+
pluginId: (_ref = template == null ? void 0 : template.pluginId) != null ? _ref : 'mui',
|
|
235
|
+
parentId,
|
|
236
|
+
props: _extends({}, props, {
|
|
237
|
+
children: label.slice(0, AI_MENU_LABEL_MAX)
|
|
238
|
+
}, to),
|
|
239
|
+
nodes: []
|
|
240
|
+
});
|
|
241
|
+
return id;
|
|
242
|
+
};
|
|
243
|
+
/** Whether a link opens a destination: the same page, or the same address. */ const opens = (node, to)=>{
|
|
244
|
+
var _node_props, _node_props1;
|
|
245
|
+
return 'screenId' in to ? (node == null ? void 0 : (_node_props = node.props) == null ? void 0 : _node_props['screenId']) === to.screenId : (node == null ? void 0 : (_node_props1 = node.props) == null ? void 0 : _node_props1['href']) === to.href;
|
|
246
|
+
};
|
|
247
|
+
/** Every link in a dropdown, at any depth (a Mega Menu's columns). */ const linksIn = (dropdown)=>[
|
|
248
|
+
...under([
|
|
249
|
+
map[dropdown]
|
|
250
|
+
])
|
|
251
|
+
].filter((id)=>id !== dropdown && isLink(id));
|
|
252
|
+
/** An entry in one list: a top-level item, or a link in a dropdown (or, in a flat list, the item itself). */ const find = (list, entry, isFlat)=>{
|
|
253
|
+
var _top_find, _linksIn_find, _top_find1;
|
|
254
|
+
const top = itemsOf(list);
|
|
255
|
+
if (!entry.parent) return (_top_find = top.find((id)=>same(labelOf(id), entry.label))) != null ? _top_find : null;
|
|
256
|
+
const parent = top.find((id)=>isDropdown(id) && same(labelOf(id), entry.parent));
|
|
257
|
+
if (parent) return (_linksIn_find = linksIn(parent).find((id)=>same(labelOf(id), entry.label))) != null ? _linksIn_find : null;
|
|
258
|
+
return isFlat ? (_top_find1 = top.find((id)=>isLink(id) && same(labelOf(id), entry.label))) != null ? _top_find1 : null : null;
|
|
259
|
+
};
|
|
260
|
+
for (const menu of menus){
|
|
261
|
+
const lists = listsOf(menu);
|
|
262
|
+
found[menu] = lists.length > 0;
|
|
263
|
+
if (!lists.length) {
|
|
264
|
+
notDone.add(`The ${menu} has no list of links to change: add them in the layout by hand.`);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
for (const list of lists){
|
|
268
|
+
const isFlat = flat(menu, list);
|
|
269
|
+
for (const entry of changes.remove){
|
|
270
|
+
const id = find(list, entry, isFlat);
|
|
271
|
+
const key = `remove:${menu}:${aiMenuEntryName(entry).toLowerCase()}`;
|
|
272
|
+
mark(key, !!id, `Took “${aiMenuEntryName(entry)}” out of the ${menu}.`, `No “${aiMenuEntryName(entry)}” in the ${menu} to take out.`);
|
|
273
|
+
if (!id) continue;
|
|
274
|
+
detach(id);
|
|
275
|
+
removeTree(id);
|
|
276
|
+
changed = true;
|
|
277
|
+
}
|
|
278
|
+
for (const entry of changes.rename){
|
|
279
|
+
var _map_id_props;
|
|
280
|
+
const id = find(list, entry, isFlat);
|
|
281
|
+
const name = entry.name.slice(0, AI_MENU_LABEL_MAX);
|
|
282
|
+
const key = `rename:${menu}:${aiMenuEntryName(entry).toLowerCase()}`;
|
|
283
|
+
mark(key, !!id, `Renamed “${aiMenuEntryName(entry)}” to “${name}” in the ${menu}.`, `No “${aiMenuEntryName(entry)}” in the ${menu} to rename.`);
|
|
284
|
+
if (!id) continue;
|
|
285
|
+
map[id].props = _extends({}, (_map_id_props = map[id].props) != null ? _map_id_props : {}, {
|
|
286
|
+
[isDropdown(id) ? 'label' : 'children']: name
|
|
287
|
+
});
|
|
288
|
+
changed = true;
|
|
289
|
+
}
|
|
290
|
+
for (const entry of changes.relink){
|
|
291
|
+
const id = find(list, entry, isFlat);
|
|
292
|
+
const key = `relink:${menu}:${aiMenuEntryName(entry).toLowerCase()}`;
|
|
293
|
+
mark(key, !!id && isLink(id), `Pointed “${aiMenuEntryName(entry)}” in the ${menu} somewhere new.`, id ? `“${aiMenuEntryName(entry)}” opens a dropdown, which links nowhere itself.` : `No “${aiMenuEntryName(entry)}” in the ${menu} to relink.`);
|
|
294
|
+
if (!id || !isLink(id)) continue;
|
|
295
|
+
setTarget(map[id], entry.to);
|
|
296
|
+
changed = true;
|
|
297
|
+
}
|
|
298
|
+
for (const entry of changes.add){
|
|
299
|
+
var _list_nodes;
|
|
300
|
+
const key = `add:${menu}:${aiMenuEntryName(entry).toLowerCase()}`;
|
|
301
|
+
if (find(list, entry, isFlat)) {
|
|
302
|
+
mark(key, true, `“${aiMenuEntryName(entry)}” was already in the ${menu}.`, '');
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
const children = (_list_nodes = list.nodes) != null ? _list_nodes : [];
|
|
306
|
+
const template = map[children.filter(isLink).slice(-1)[0]];
|
|
307
|
+
// After the list's last item, else after its brand: before a search,
|
|
308
|
+
// a mode switch or a call to action that follows them.
|
|
309
|
+
const lastOf = (test)=>children.reduce((at, id, index)=>test(id) ? index : at, -1);
|
|
310
|
+
const lastItem = lastOf(isItem) !== -1 ? lastOf(isItem) : lastOf((id)=>{
|
|
311
|
+
var _map_id;
|
|
312
|
+
return ((_map_id = map[id]) == null ? void 0 : _map_id.componentId) === LINK;
|
|
313
|
+
});
|
|
314
|
+
if (!entry.parent || isFlat) {
|
|
315
|
+
var _entry_after;
|
|
316
|
+
// After its parent in a flat list, else after the item it is to
|
|
317
|
+
// follow, else after the list's last item.
|
|
318
|
+
const parentAt = entry.parent ? children.findIndex((id)=>isItem(id) && same(labelOf(id), entry.parent)) : -1;
|
|
319
|
+
const afterAt = !entry.parent && ((_entry_after = entry.after) == null ? void 0 : _entry_after.length) ? children.findIndex((id)=>{
|
|
320
|
+
var _entry_after;
|
|
321
|
+
return isLink(id) && ((_entry_after = entry.after) != null ? _entry_after : []).some((to)=>opens(map[id], to));
|
|
322
|
+
}) : -1;
|
|
323
|
+
let at = parentAt !== -1 ? parentAt : afterAt !== -1 ? afterAt : lastItem;
|
|
324
|
+
if (parentAt !== -1) {
|
|
325
|
+
// After the entries already following the parent from an earlier add.
|
|
326
|
+
while(at + 1 < children.length && isLink(children[at + 1]) && String(children[at + 1]).startsWith('ai_nav_'))at += 1;
|
|
327
|
+
}
|
|
328
|
+
const id = linkLike(template, list.$id, entry.label, entry.to);
|
|
329
|
+
list.nodes = [
|
|
330
|
+
...children.slice(0, at + 1),
|
|
331
|
+
id,
|
|
332
|
+
...children.slice(at + 1)
|
|
333
|
+
];
|
|
334
|
+
} else {
|
|
335
|
+
var _map_linksIn_, _inside_nodes;
|
|
336
|
+
let dropdown = children.find((id)=>isDropdown(id) && same(labelOf(id), entry.parent));
|
|
337
|
+
if (!dropdown) {
|
|
338
|
+
// A Dropdown Menu of that name, where its link of that name was, else last.
|
|
339
|
+
dropdown = newId();
|
|
340
|
+
const own = children.find((id)=>isLink(id) && same(labelOf(id), entry.parent));
|
|
341
|
+
map[dropdown] = {
|
|
342
|
+
$id: dropdown,
|
|
343
|
+
componentId: NAV_MENU,
|
|
344
|
+
pluginId: 'mui',
|
|
345
|
+
parentId: list.$id,
|
|
346
|
+
props: {
|
|
347
|
+
label: entry.parent.slice(0, AI_MENU_LABEL_MAX)
|
|
348
|
+
},
|
|
349
|
+
nodes: own ? [
|
|
350
|
+
own
|
|
351
|
+
] : []
|
|
352
|
+
};
|
|
353
|
+
if (own) {
|
|
354
|
+
map[own].parentId = dropdown;
|
|
355
|
+
list.nodes = children.map((id)=>id === own ? dropdown : id);
|
|
356
|
+
} else {
|
|
357
|
+
list.nodes = [
|
|
358
|
+
...children.slice(0, lastItem + 1),
|
|
359
|
+
dropdown,
|
|
360
|
+
...children.slice(lastItem + 1)
|
|
361
|
+
];
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
const inside = map[dropdown];
|
|
365
|
+
const id = linkLike((_map_linksIn_ = map[linksIn(dropdown)[0]]) != null ? _map_linksIn_ : template, dropdown, entry.label, entry.to);
|
|
366
|
+
inside.nodes = [
|
|
367
|
+
...(_inside_nodes = inside.nodes) != null ? _inside_nodes : [],
|
|
368
|
+
id
|
|
369
|
+
];
|
|
370
|
+
}
|
|
371
|
+
changed = true;
|
|
372
|
+
mark(key, true, `Added “${aiMenuEntryName(entry)}” to the ${menu}.`, '');
|
|
373
|
+
}
|
|
374
|
+
if (changes.order.length) {
|
|
375
|
+
var _list_nodes1;
|
|
376
|
+
const children = (_list_nodes1 = list.nodes) != null ? _list_nodes1 : [];
|
|
377
|
+
const slots = children.map((id, index)=>isItem(id) ? index : -1).filter((index)=>index !== -1);
|
|
378
|
+
const items = slots.map((index)=>children[index]);
|
|
379
|
+
const named = changes.order.flatMap((label)=>items.filter((id)=>same(labelOf(id), label)).slice(0, 1));
|
|
380
|
+
const ordered = [
|
|
381
|
+
...new Set([
|
|
382
|
+
...named,
|
|
383
|
+
...items
|
|
384
|
+
])
|
|
385
|
+
];
|
|
386
|
+
if (ordered.some((id, index)=>id !== items[index])) {
|
|
387
|
+
const next = [
|
|
388
|
+
...children
|
|
389
|
+
];
|
|
390
|
+
slots.forEach((slot, index)=>{
|
|
391
|
+
next[slot] = ordered[index];
|
|
392
|
+
});
|
|
393
|
+
list.nodes = next;
|
|
394
|
+
changed = true;
|
|
395
|
+
}
|
|
396
|
+
for (const label of changes.order){
|
|
397
|
+
mark(`order:${menu}:${label.toLowerCase()}`, items.some((id)=>same(labelOf(id), label)), `Put “${label}” in its place in the ${menu}.`, `No “${label}” in the ${menu} to put in order.`);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
// A link taken out leaves no dropdown with no link in it, and no footer
|
|
403
|
+
// heading or column with nothing under it (AGL-3735).
|
|
404
|
+
if (changed && changes.remove.length) aiLayoutRepairFrameHollows(map);
|
|
405
|
+
const entries = [
|
|
406
|
+
...outcomes.values()
|
|
407
|
+
];
|
|
408
|
+
return {
|
|
409
|
+
nodes: changed ? map : null,
|
|
410
|
+
found,
|
|
411
|
+
done: [
|
|
412
|
+
...new Set(entries.filter((entry)=>entry.ok).map((entry)=>entry.done))
|
|
413
|
+
],
|
|
414
|
+
notDone: [
|
|
415
|
+
...notDone,
|
|
416
|
+
...new Set(entries.filter((entry)=>!entry.ok).map((entry)=>entry.failed))
|
|
417
|
+
]
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
// ── The change as an item's arguments carry it ───────────────────────────
|
|
421
|
+
/** How an entry names a parent, a label and a destination: `Services > Roofing => /roofing`. */ const ARROW = /\s*=>\s*/;
|
|
422
|
+
const PARENT = /\s*>\s*/;
|
|
423
|
+
/** An entry's parent and label: `Services > Roofing`, or `Roofing`. */ function entryRefOf(text) {
|
|
424
|
+
const parts = text.split(PARENT).map((part)=>said(part)).filter(Boolean);
|
|
425
|
+
if (!parts.length || parts.length > 2) return null;
|
|
426
|
+
const label = parts[parts.length - 1].slice(0, AI_MENU_LABEL_MAX);
|
|
427
|
+
return {
|
|
428
|
+
parent: parts.length === 2 ? parts[0].slice(0, AI_MENU_LABEL_MAX) : null,
|
|
429
|
+
label
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
const list = (value)=>Array.isArray(value) ? value.filter((one)=>typeof one === 'string').map(said).filter(Boolean).slice(0, AI_MENU_CHANGES_MAX) : [];
|
|
433
|
+
/**
|
|
434
|
+
* A navigation item's change, read off its arguments (AGL-3728). Each entry
|
|
435
|
+
* is words: `add` and `relink` take `Label => destination` (a parent first
|
|
436
|
+
* as `Parent > Label`), `remove` the label, `rename` `Old => New`, `order`
|
|
437
|
+
* labels. `target` turns a destination into a page or an address, or `null`
|
|
438
|
+
* for one this site cannot link, which leaves that entry out with a sentence.
|
|
439
|
+
*/ export function aiMenuChangesOf(args, target) {
|
|
440
|
+
const problems = [];
|
|
441
|
+
const changes = aiNoMenuChanges();
|
|
442
|
+
const linked = (entry, verb)=>{
|
|
443
|
+
const [name, destination, ...rest] = entry.split(ARROW);
|
|
444
|
+
const ref = entryRefOf(name != null ? name : '');
|
|
445
|
+
if (!ref || !said(destination) || rest.length) {
|
|
446
|
+
problems.push(`“${entry}” is not “Label => page or address”, so it was left out.`);
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
const to = target(said(destination));
|
|
450
|
+
if (!to) {
|
|
451
|
+
problems.push(`“${aiMenuEntryName(ref)}” links “${said(destination)}”, which is no page or address on this site, so it was left out.`);
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
changes[verb].push(_extends({}, ref, {
|
|
455
|
+
to
|
|
456
|
+
}));
|
|
457
|
+
};
|
|
458
|
+
for (const entry of list(args['add']))linked(entry, 'add');
|
|
459
|
+
for (const entry of list(args['relink']))linked(entry, 'relink');
|
|
460
|
+
for (const entry of list(args['remove'])){
|
|
461
|
+
const ref = entryRefOf(entry);
|
|
462
|
+
if (ref) changes.remove.push(ref);
|
|
463
|
+
else problems.push(`“${entry}” names no menu item, so it was left out.`);
|
|
464
|
+
}
|
|
465
|
+
for (const entry of list(args['rename'])){
|
|
466
|
+
const [from, to, ...rest] = entry.split(ARROW);
|
|
467
|
+
const ref = entryRefOf(from != null ? from : '');
|
|
468
|
+
const name = said(to);
|
|
469
|
+
if (!ref || !name || rest.length) problems.push(`“${entry}” is not “Old name => New name”, so it was left out.`);
|
|
470
|
+
else changes.rename.push(_extends({}, ref, {
|
|
471
|
+
name: name.slice(0, AI_MENU_LABEL_MAX)
|
|
472
|
+
}));
|
|
473
|
+
}
|
|
474
|
+
changes.order = list(args['order']).map((label)=>label.slice(0, AI_MENU_LABEL_MAX));
|
|
475
|
+
return {
|
|
476
|
+
changes,
|
|
477
|
+
problems
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
/** A change that does nothing, to build one from. */ export function aiNoMenuChanges() {
|
|
481
|
+
return {
|
|
482
|
+
add: [],
|
|
483
|
+
remove: [],
|
|
484
|
+
rename: [],
|
|
485
|
+
relink: [],
|
|
486
|
+
order: []
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
/** Whether a change does anything at all. */ export function aiMenuChangesEmpty(changes) {
|
|
490
|
+
return !changes.add.length && !changes.remove.length && !changes.rename.length && !changes.relink.length && !changes.order.length;
|
|
491
|
+
}
|
|
492
|
+
/** The menus an item's `menu` names: the header, the footer, or both. */ export function aiMenusOf(value) {
|
|
493
|
+
if (value === 'footer') return [
|
|
494
|
+
'footer'
|
|
495
|
+
];
|
|
496
|
+
if (value === 'both') return [
|
|
497
|
+
'header',
|
|
498
|
+
'footer'
|
|
499
|
+
];
|
|
500
|
+
return [
|
|
501
|
+
'header'
|
|
502
|
+
];
|
|
503
|
+
}
|
|
504
|
+
/** The `new:` references an entry's destination makes: what the item must be built after. */ export function aiMenuNewRefs(args) {
|
|
505
|
+
const refs = [];
|
|
506
|
+
for (const key of [
|
|
507
|
+
'add',
|
|
508
|
+
'relink'
|
|
509
|
+
]){
|
|
510
|
+
for (const entry of list(args[key])){
|
|
511
|
+
const destination = said(entry.split(ARROW)[1]);
|
|
512
|
+
if (/^new:/i.test(destination) && !refs.includes(destination)) refs.push(destination);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return refs;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
//# sourceMappingURL=ai-layout-menus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-layout-menus.ts"],"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\n/**\n * A SITE'S MENUS, CHANGED BY CODE (AGL-3728).\n *\n * A site's header and footer menus are not a separate document: they are the\n * Besigner's own elements in the layout's node tree — Page Links\n * (`muiScreenLink`) in a list in the header, the same list again in the phone\n * menu's Drawer, Dropdown Menus (`muiNavMenu`, `muiMegaMenu`) holding more\n * Page Links, and the footer's list of Page Links. That is what a person\n * edits in the Besigner, and what this edits, so a menu the AI changed opens\n * in the editor exactly as one a person changed.\n *\n * A change is planned as words — add \"About\", take \"Blog\" out, call\n * \"Services\" \"What we do\", link \"Shop\" to a page, put \"Contact\" last — and\n * applied here, in code, to every list of the menu it names:\n *\n * - THE HEADER's lists are the lists of links inside its App Bar (or an\n * element that renders `header`): the bar's own row and the phone menu's.\n * Where it has lists that render `nav`, only those are its menu, so the\n * brand and an account link beside it never are. Failing any list, a\n * Toolbar holding a link (the brand's counts), else the first Toolbar.\n * The brand (a link the compiler named `brand`) is never a menu item, and\n * an item added beside nothing but the brand goes after it.\n * - THE FOOTER's list is the longest list of links inside the element that\n * renders `footer`.\n *\n * Recognized the way a store's links are added to a layout\n * (`aiLayoutWithStoreLinks`, AGL-3676). A layout with no list for a menu is\n * left as it is, and the change says what to do by hand.\n *\n * A new link copies a link already in the list it joins — its look, and in\n * the phone menu the interaction that closes it — so it looks like its\n * neighbours. A link added under a parent (\"Services > Roofing\") goes into the\n * Dropdown Menu of that name in a bar's row, made where there is none (the\n * link of that name, if any, becoming its first entry); a phone menu and a\n * footer have no dropdowns, so there it joins the list after its parent.\n *\n * ONE implementation for every menu change the AI makes (AGL-3747): the\n * `navigation` op's (`ai-job-navigation-step.ts`), and the header entries a\n * guided site start adds to its layout when it publishes\n * (`aiLayoutWithNavigation` in `ai-site-publish.ts`), including the /blog\n * entry a retried posts part puts back.\n *\n * Pure: nodes in, nodes out.\n */\n\nimport { aiLayoutRepairFrameHollows } from '../layout-language/ai-layout-frame-hollows'\n\n/** A menu of a site's layout. */\nexport type AiMenuName = 'header' | 'footer'\n\nexport const AI_MENU_NAMES: readonly AiMenuName[] = ['header', 'footer']\n\n/** Where a menu item goes: one of the site's pages, by id, or an address. */\nexport type AiMenuTarget = { screenId: string } | { href: string }\n\n/** One entry a change names: a top-level item, or one under a parent dropdown. */\nexport interface AiMenuEntryRef {\n /** The dropdown it is under, by its label; `null` for a top-level item. */\n parent: string | null\n label: string\n}\n\n/** An entry to add, and where it goes. */\nexport type AiMenuAddition = AiMenuEntryRef & {\n to: AiMenuTarget\n /**\n * A top-level entry goes right after the first item linking one of these\n * (a page by id, an address), where the menu has one, instead of last. Set\n * by code, never read off a planner's words: the blog's entry, put back\n * second after Home (AGL-3747).\n */\n after?: readonly AiMenuTarget[]\n}\n\n/** What a navigation change does to a menu. */\nexport interface AiMenuChanges {\n add: AiMenuAddition[]\n remove: AiMenuEntryRef[]\n rename: Array<AiMenuEntryRef & { name: string }>\n relink: Array<AiMenuEntryRef & { to: AiMenuTarget }>\n /** Top-level labels, in the order wanted; the rest keep theirs, after them. */\n order: string[]\n}\n\n/** What applying a change came to. */\nexport interface AiMenusResult {\n /** The layout's nodes with the change made, or `null` where nothing changed. */\n nodes: Record<string, unknown> | null\n /** Whether the layout has a list for each menu asked about. */\n found: Partial<Record<AiMenuName, boolean>>\n /** What was done, as sentences. */\n done: string[]\n /** What could not be done, and why, as sentences. */\n notDone: string[]\n}\n\nconst LINK = 'muiScreenLink'\n/** The Besigner's Dropdown Menu and Mega Menu: a labelled item holding links. Persisted ids. */\nexport const AI_MENU_DROPDOWNS: readonly string[] = ['muiNavMenu', 'muiMegaMenu']\nconst NAV_MENU = 'muiNavMenu'\nconst DRAWER = 'muiDrawer'\n/** The most items a menu may be asked to change in one go. */\nexport const AI_MENU_CHANGES_MAX = 12\n/** The longest label a menu item takes. */\nexport const AI_MENU_LABEL_MAX = 40\n\ninterface Node {\n $id: string\n componentId?: string\n pluginId?: string\n parentId?: string | null\n nodes?: string[]\n props?: Record<string, unknown>\n sx?: Record<string, unknown>\n [key: string]: unknown\n}\n\nconst renders = (node: Node, element: string) =>\n node.props?.['element'] === element || node.props?.['component'] === element || node.componentId === element\n\nconst said = (value: unknown): string => (typeof value === 'string' ? value.replace(/\\s+/g, ' ').trim() : '')\nconst same = (a: string, b: string) => a.trim().toLowerCase() === b.trim().toLowerCase()\n\n/** Where a menu change says an entry lives, in words: `Roofing`, `Services › Roofing`. */\nexport function aiMenuEntryName(entry: AiMenuEntryRef): string {\n return entry.parent ? `${entry.parent} › ${entry.label}` : entry.label\n}\n\n/**\n * The layout's nodes with a navigation change made to the menus named\n * (AGL-3728). Each menu's lists all take the same change, so the bar and the\n * phone menu never disagree. `newId` mints a node id; the default is a\n * counter under `ai_nav_`.\n */\nexport function aiLayoutWithMenuChanges(\n nodes: Readonly<Record<string, unknown>>,\n menus: readonly AiMenuName[],\n changes: AiMenuChanges,\n options: { newId?: () => string } = {},\n): AiMenusResult {\n const map: Record<string, Node> = {}\n for (const [id, raw] of Object.entries(nodes as Record<string, Node>)) {\n if (!raw || typeof raw !== 'object') continue\n map[id] = {\n ...raw,\n $id: typeof raw.$id === 'string' && raw.$id ? raw.$id : id,\n ...(raw.props ? { props: { ...raw.props } } : {}),\n ...(raw.nodes ? { nodes: [...raw.nodes] } : {}),\n }\n }\n let counter = 0\n const newId =\n options.newId ??\n (() => {\n counter += 1\n while (map[`ai_nav_${counter}`]) counter += 1\n return `ai_nav_${counter}`\n })\n const all = Object.values(map)\n const under = (roots: readonly Node[]): Set<string> => {\n const seen = new Set<string>()\n const queue = roots.map((root) => root.$id)\n while (queue.length) {\n const id = queue.shift() as string\n if (seen.has(id) || !map[id]) continue\n seen.add(id)\n queue.push(...(map[id].nodes ?? []))\n }\n return seen\n }\n const isBrand = (id: string) => /brand/i.test(id)\n const isLink = (id: string) => map[id]?.componentId === LINK && !isBrand(id)\n const isDropdown = (id: string) => AI_MENU_DROPDOWNS.includes(String(map[id]?.componentId))\n const isItem = (id: string) => isLink(id) || isDropdown(id)\n const itemsOf = (list: Node) => (list.nodes ?? []).filter(isItem)\n const labelOf = (id: string) => said(isDropdown(id) ? map[id]?.props?.['label'] : map[id]?.props?.['children'])\n\n // ── The lists each menu is ───────────────────────────────────────────\n const listsOf = (menu: AiMenuName): Node[] => {\n if (menu === 'footer') {\n const ids = under(all.filter((node) => renders(node, 'footer')))\n const longest = [...ids]\n .map((id) => map[id])\n .filter((node) => (node.nodes ?? []).filter(isLink).length >= 2)\n .sort((a, b) => (b.nodes ?? []).filter(isLink).length - (a.nodes ?? []).filter(isLink).length)[0]\n return longest ? [longest] : []\n }\n const ids = under(all.filter((node) => node.componentId === 'muiAppBar' || renders(node, 'header')))\n const lists = [...ids].map((id) => map[id]).filter((node) => itemsOf(node).length >= 2)\n const landmarks = lists.filter((node) => renders(node, 'nav'))\n if (landmarks.length) return landmarks\n if (lists.length) return lists\n // A bar's Toolbar holding a link, the brand's included (a starter's\n // header is a brand and a search), else its first Toolbar.\n const toolbars = all.filter((node) => node.componentId === 'muiToolbar')\n const toolbar = toolbars.find((node) => (node.nodes ?? []).some((id) => map[id]?.componentId === LINK)) ?? toolbars[0]\n return toolbar ? [toolbar] : []\n }\n // A phone menu (in a Drawer) and a footer hold no dropdowns: their entries stay flat.\n const drawerIds = under(all.filter((node) => node.componentId === DRAWER))\n const flat = (menu: AiMenuName, list: Node) => menu === 'footer' || drawerIds.has(list.$id)\n\n const found: Partial<Record<AiMenuName, boolean>> = {}\n const notDone = new Set<string>()\n // What each entry came to across a menu's lists: done where any list did it.\n const outcomes = new Map<string, { ok: boolean; done: string; failed: string }>()\n const mark = (key: string, ok: boolean, done: string, failed: string) => {\n const was = outcomes.get(key)\n outcomes.set(key, { ok: ok || (was?.ok ?? false), done, failed: was && !was.ok && !ok ? was.failed : failed })\n }\n let changed = false\n\n const removeTree = (id: string) => {\n for (const child of [...(map[id]?.nodes ?? [])]) removeTree(child)\n delete map[id]\n }\n const detach = (id: string) => {\n for (const node of Object.values(map)) {\n if (node.nodes?.includes(id)) node.nodes = node.nodes.filter((child) => child !== id)\n }\n }\n const setTarget = (node: Node, to: AiMenuTarget) => {\n const props = { ...(node.props ?? {}) }\n delete props['screenId']\n delete props['href']\n node.props = { ...props, ...to }\n }\n /** A new link like the list's own, else a plain one. */\n const linkLike = (template: Node | undefined, parentId: string, label: string, to: AiMenuTarget): string => {\n const id = newId()\n const props: Record<string, unknown> = template?.props\n ? { ...template.props }\n : { renderAs: 'link', color: 'inherit' }\n delete props['screenId']\n delete props['href']\n map[id] = {\n ...(template ?? { sx: { textDecoration: 'none', whiteSpace: 'nowrap' } }),\n $id: id,\n componentId: LINK,\n pluginId: template?.pluginId ?? 'mui',\n parentId,\n props: { ...props, children: label.slice(0, AI_MENU_LABEL_MAX), ...to },\n nodes: [],\n }\n return id\n }\n /** Whether a link opens a destination: the same page, or the same address. */\n const opens = (node: Node | undefined, to: AiMenuTarget) =>\n 'screenId' in to ? node?.props?.['screenId'] === to.screenId : node?.props?.['href'] === to.href\n /** Every link in a dropdown, at any depth (a Mega Menu's columns). */\n const linksIn = (dropdown: string) => [...under([map[dropdown]])].filter((id) => id !== dropdown && isLink(id))\n /** An entry in one list: a top-level item, or a link in a dropdown (or, in a flat list, the item itself). */\n const find = (list: Node, entry: AiMenuEntryRef, isFlat: boolean): string | null => {\n const top = itemsOf(list)\n if (!entry.parent) return top.find((id) => same(labelOf(id), entry.label)) ?? null\n const parent = top.find((id) => isDropdown(id) && same(labelOf(id), entry.parent as string))\n if (parent) return linksIn(parent).find((id) => same(labelOf(id), entry.label)) ?? null\n return isFlat ? (top.find((id) => isLink(id) && same(labelOf(id), entry.label)) ?? null) : null\n }\n\n for (const menu of menus) {\n const lists = listsOf(menu)\n found[menu] = lists.length > 0\n if (!lists.length) {\n notDone.add(`The ${menu} has no list of links to change: add them in the layout by hand.`)\n continue\n }\n for (const list of lists) {\n const isFlat = flat(menu, list)\n for (const entry of changes.remove) {\n const id = find(list, entry, isFlat)\n const key = `remove:${menu}:${aiMenuEntryName(entry).toLowerCase()}`\n mark(key, !!id, `Took “${aiMenuEntryName(entry)}” out of the ${menu}.`, `No “${aiMenuEntryName(entry)}” in the ${menu} to take out.`)\n if (!id) continue\n detach(id)\n removeTree(id)\n changed = true\n }\n for (const entry of changes.rename) {\n const id = find(list, entry, isFlat)\n const name = entry.name.slice(0, AI_MENU_LABEL_MAX)\n const key = `rename:${menu}:${aiMenuEntryName(entry).toLowerCase()}`\n mark(key, !!id, `Renamed “${aiMenuEntryName(entry)}” to “${name}” in the ${menu}.`, `No “${aiMenuEntryName(entry)}” in the ${menu} to rename.`)\n if (!id) continue\n map[id].props = { ...(map[id].props ?? {}), [isDropdown(id) ? 'label' : 'children']: name }\n changed = true\n }\n for (const entry of changes.relink) {\n const id = find(list, entry, isFlat)\n const key = `relink:${menu}:${aiMenuEntryName(entry).toLowerCase()}`\n mark(\n key,\n !!id && isLink(id),\n `Pointed “${aiMenuEntryName(entry)}” in the ${menu} somewhere new.`,\n id ? `“${aiMenuEntryName(entry)}” opens a dropdown, which links nowhere itself.` : `No “${aiMenuEntryName(entry)}” in the ${menu} to relink.`,\n )\n if (!id || !isLink(id)) continue\n setTarget(map[id], entry.to)\n changed = true\n }\n for (const entry of changes.add) {\n const key = `add:${menu}:${aiMenuEntryName(entry).toLowerCase()}`\n if (find(list, entry, isFlat)) {\n mark(key, true, `“${aiMenuEntryName(entry)}” was already in the ${menu}.`, '')\n continue\n }\n const children = list.nodes ?? []\n const template = map[children.filter(isLink).slice(-1)[0]]\n // After the list's last item, else after its brand: before a search,\n // a mode switch or a call to action that follows them.\n const lastOf = (test: (id: string) => boolean) => children.reduce((at, id, index) => (test(id) ? index : at), -1)\n const lastItem = lastOf(isItem) !== -1 ? lastOf(isItem) : lastOf((id) => map[id]?.componentId === LINK)\n if (!entry.parent || isFlat) {\n // After its parent in a flat list, else after the item it is to\n // follow, else after the list's last item.\n const parentAt = entry.parent ? children.findIndex((id) => isItem(id) && same(labelOf(id), entry.parent as string)) : -1\n const afterAt = !entry.parent && entry.after?.length ? children.findIndex((id) => isLink(id) && (entry.after ?? []).some((to) => opens(map[id], to))) : -1\n let at = parentAt !== -1 ? parentAt : afterAt !== -1 ? afterAt : lastItem\n if (parentAt !== -1) {\n // After the entries already following the parent from an earlier add.\n while (at + 1 < children.length && isLink(children[at + 1]) && String(children[at + 1]).startsWith('ai_nav_')) at += 1\n }\n const id = linkLike(template, list.$id, entry.label, entry.to)\n list.nodes = [...children.slice(0, at + 1), id, ...children.slice(at + 1)]\n } else {\n let dropdown = children.find((id) => isDropdown(id) && same(labelOf(id), entry.parent as string))\n if (!dropdown) {\n // A Dropdown Menu of that name, where its link of that name was, else last.\n dropdown = newId()\n const own = children.find((id) => isLink(id) && same(labelOf(id), entry.parent as string))\n map[dropdown] = {\n $id: dropdown,\n componentId: NAV_MENU,\n pluginId: 'mui',\n parentId: list.$id,\n props: { label: (entry.parent as string).slice(0, AI_MENU_LABEL_MAX) },\n nodes: own ? [own] : [],\n }\n if (own) {\n map[own].parentId = dropdown\n list.nodes = children.map((id) => (id === own ? (dropdown as string) : id))\n } else {\n list.nodes = [...children.slice(0, lastItem + 1), dropdown, ...children.slice(lastItem + 1)]\n }\n }\n const inside = map[dropdown]\n const id = linkLike(map[linksIn(dropdown)[0]] ?? template, dropdown, entry.label, entry.to)\n inside.nodes = [...(inside.nodes ?? []), id]\n }\n changed = true\n mark(key, true, `Added “${aiMenuEntryName(entry)}” to the ${menu}.`, '')\n }\n if (changes.order.length) {\n const children = list.nodes ?? []\n const slots = children.map((id, index) => (isItem(id) ? index : -1)).filter((index) => index !== -1)\n const items = slots.map((index) => children[index])\n const named = changes.order.flatMap((label) => items.filter((id) => same(labelOf(id), label)).slice(0, 1))\n const ordered = [...new Set([...named, ...items])]\n if (ordered.some((id, index) => id !== items[index])) {\n const next = [...children]\n slots.forEach((slot, index) => {\n next[slot] = ordered[index]\n })\n list.nodes = next\n changed = true\n }\n for (const label of changes.order) {\n mark(\n `order:${menu}:${label.toLowerCase()}`,\n items.some((id) => same(labelOf(id), label)),\n `Put “${label}” in its place in the ${menu}.`,\n `No “${label}” in the ${menu} to put in order.`,\n )\n }\n }\n }\n }\n // A link taken out leaves no dropdown with no link in it, and no footer\n // heading or column with nothing under it (AGL-3735).\n if (changed && changes.remove.length) aiLayoutRepairFrameHollows(map as unknown as Record<string, unknown>)\n const entries = [...outcomes.values()]\n return {\n nodes: changed ? (map as Record<string, unknown>) : null,\n found,\n done: [...new Set(entries.filter((entry) => entry.ok).map((entry) => entry.done))],\n notDone: [...notDone, ...new Set(entries.filter((entry) => !entry.ok).map((entry) => entry.failed))],\n }\n}\n\n// ── The change as an item's arguments carry it ───────────────────────────\n\n/** How an entry names a parent, a label and a destination: `Services > Roofing => /roofing`. */\nconst ARROW = /\\s*=>\\s*/\nconst PARENT = /\\s*>\\s*/\n\n/** What reading an item's arguments came to: the change, and what could not be read. */\nexport interface AiMenuChangesRead {\n changes: AiMenuChanges\n problems: string[]\n}\n\n/** An entry's parent and label: `Services > Roofing`, or `Roofing`. */\nfunction entryRefOf(text: string): AiMenuEntryRef | null {\n const parts = text.split(PARENT).map((part) => said(part)).filter(Boolean)\n if (!parts.length || parts.length > 2) return null\n const label = parts[parts.length - 1].slice(0, AI_MENU_LABEL_MAX)\n return { parent: parts.length === 2 ? parts[0].slice(0, AI_MENU_LABEL_MAX) : null, label }\n}\n\nconst list = (value: unknown): string[] =>\n Array.isArray(value) ? value.filter((one): one is string => typeof one === 'string').map(said).filter(Boolean).slice(0, AI_MENU_CHANGES_MAX) : []\n\n/**\n * A navigation item's change, read off its arguments (AGL-3728). Each entry\n * is words: `add` and `relink` take `Label => destination` (a parent first\n * as `Parent > Label`), `remove` the label, `rename` `Old => New`, `order`\n * labels. `target` turns a destination into a page or an address, or `null`\n * for one this site cannot link, which leaves that entry out with a sentence.\n */\nexport function aiMenuChangesOf(\n args: Readonly<Record<string, unknown>>,\n target: (destination: string) => AiMenuTarget | null,\n): AiMenuChangesRead {\n const problems: string[] = []\n const changes = aiNoMenuChanges()\n const linked = (entry: string, verb: 'add' | 'relink') => {\n const [name, destination, ...rest] = entry.split(ARROW)\n const ref = entryRefOf(name ?? '')\n if (!ref || !said(destination) || rest.length) {\n problems.push(`“${entry}” is not “Label => page or address”, so it was left out.`)\n return\n }\n const to = target(said(destination))\n if (!to) {\n problems.push(`“${aiMenuEntryName(ref)}” links “${said(destination)}”, which is no page or address on this site, so it was left out.`)\n return\n }\n changes[verb].push({ ...ref, to })\n }\n for (const entry of list(args['add'])) linked(entry, 'add')\n for (const entry of list(args['relink'])) linked(entry, 'relink')\n for (const entry of list(args['remove'])) {\n const ref = entryRefOf(entry)\n if (ref) changes.remove.push(ref)\n else problems.push(`“${entry}” names no menu item, so it was left out.`)\n }\n for (const entry of list(args['rename'])) {\n const [from, to, ...rest] = entry.split(ARROW)\n const ref = entryRefOf(from ?? '')\n const name = said(to)\n if (!ref || !name || rest.length) problems.push(`“${entry}” is not “Old name => New name”, so it was left out.`)\n else changes.rename.push({ ...ref, name: name.slice(0, AI_MENU_LABEL_MAX) })\n }\n changes.order = list(args['order']).map((label) => label.slice(0, AI_MENU_LABEL_MAX))\n return { changes, problems }\n}\n\n/** A change that does nothing, to build one from. */\nexport function aiNoMenuChanges(): AiMenuChanges {\n return { add: [], remove: [], rename: [], relink: [], order: [] }\n}\n\n/** Whether a change does anything at all. */\nexport function aiMenuChangesEmpty(changes: AiMenuChanges): boolean {\n return !changes.add.length && !changes.remove.length && !changes.rename.length && !changes.relink.length && !changes.order.length\n}\n\n/** The menus an item's `menu` names: the header, the footer, or both. */\nexport function aiMenusOf(value: unknown): AiMenuName[] {\n if (value === 'footer') return ['footer']\n if (value === 'both') return ['header', 'footer']\n return ['header']\n}\n\n/** The `new:` references an entry's destination makes: what the item must be built after. */\nexport function aiMenuNewRefs(args: Readonly<Record<string, unknown>>): string[] {\n const refs: string[] = []\n for (const key of ['add', 'relink'] as const) {\n for (const entry of list(args[key])) {\n const destination = said(entry.split(ARROW)[1])\n if (/^new:/i.test(destination) && !refs.includes(destination)) refs.push(destination)\n }\n }\n return refs\n}\n"],"names":["aiLayoutRepairFrameHollows","AI_MENU_NAMES","LINK","AI_MENU_DROPDOWNS","NAV_MENU","DRAWER","AI_MENU_CHANGES_MAX","AI_MENU_LABEL_MAX","renders","node","element","props","componentId","said","value","replace","trim","same","a","b","toLowerCase","aiMenuEntryName","entry","parent","label","aiLayoutWithMenuChanges","nodes","menus","changes","options","map","id","raw","Object","entries","$id","counter","newId","all","values","under","roots","seen","Set","queue","root","length","shift","has","add","push","isBrand","test","isLink","isDropdown","includes","String","isItem","itemsOf","list","filter","labelOf","listsOf","menu","toolbars","ids","longest","sort","lists","landmarks","toolbar","find","some","drawerIds","flat","found","notDone","outcomes","Map","mark","key","ok","done","failed","was","get","set","changed","removeTree","child","detach","setTarget","to","linkLike","template","parentId","renderAs","color","sx","textDecoration","whiteSpace","pluginId","children","slice","opens","screenId","href","linksIn","dropdown","isFlat","top","remove","rename","name","relink","lastOf","reduce","at","index","lastItem","parentAt","findIndex","afterAt","after","startsWith","inside","own","order","slots","items","named","flatMap","ordered","next","forEach","slot","ARROW","PARENT","entryRefOf","text","parts","split","part","Boolean","Array","isArray","one","aiMenuChangesOf","args","target","problems","aiNoMenuChanges","linked","verb","destination","rest","ref","from","aiMenuChangesEmpty","aiMenusOf","aiMenuNewRefs","refs"],"mappings":"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"}
|