nfunc-mcp 0.3.0 → 0.4.0
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/README.md +84 -376
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mappers/labFieldComparator.d.ts +62 -0
- package/dist/mappers/labFieldComparator.js +134 -0
- package/dist/mappers/labFieldComparator.js.map +1 -0
- package/dist/mappers/psiAggregator.d.ts +130 -0
- package/dist/mappers/psiAggregator.js +293 -0
- package/dist/mappers/psiAggregator.js.map +1 -0
- package/dist/mappers/webVitalsMapper.d.ts +52 -0
- package/dist/mappers/webVitalsMapper.js +131 -0
- package/dist/mappers/webVitalsMapper.js.map +1 -0
- package/dist/tools/performanceAudit.d.ts +2 -0
- package/dist/tools/performanceAudit.js +446 -0
- package/dist/tools/performanceAudit.js.map +1 -0
- package/dist/tools/performanceAuditPlan.d.ts +2 -0
- package/dist/tools/performanceAuditPlan.js +438 -0
- package/dist/tools/performanceAuditPlan.js.map +1 -0
- package/dist/utils/csvReader.d.ts +20 -0
- package/dist/utils/csvReader.js +172 -0
- package/dist/utils/csvReader.js.map +1 -0
- package/dist/utils/httpClient.d.ts +84 -0
- package/dist/utils/httpClient.js +171 -0
- package/dist/utils/httpClient.js.map +1 -0
- package/dist/utils/psiAuth.d.ts +26 -0
- package/dist/utils/psiAuth.js +36 -0
- package/dist/utils/psiAuth.js.map +1 -0
- package/dist/utils/psiParser.d.ts +124 -0
- package/dist/utils/psiParser.js +200 -0
- package/dist/utils/psiParser.js.map +1 -0
- package/dist/utils/publicUrl.d.ts +17 -0
- package/dist/utils/publicUrl.js +115 -0
- package/dist/utils/publicUrl.js.map +1 -0
- package/dist/utils/sitemapReader.d.ts +27 -0
- package/dist/utils/sitemapReader.js +272 -0
- package/dist/utils/sitemapReader.js.map +1 -0
- package/dist/utils/urlClassifier.d.ts +45 -0
- package/dist/utils/urlClassifier.js +267 -0
- package/dist/utils/urlClassifier.js.map +1 -0
- package/docs/manual.md +558 -0
- package/docs/psi-report-spec.md +174 -0
- package/package.json +13 -3
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { isSessionGated } from "./publicUrl.js";
|
|
2
|
+
/**
|
|
3
|
+
* Query parameters that identify the visitor or the campaign rather than the
|
|
4
|
+
* page. Left in, they would split one template into dozens of "shapes" that
|
|
5
|
+
* all render identically.
|
|
6
|
+
*/
|
|
7
|
+
const TRACKING_PARAMS = /^(utm_|gclid|fbclid|msclkid|mc_cid|mc_eid|_ga|igshid|srsltid|ref|referrer|source|cmpid|campaign)/i;
|
|
8
|
+
/**
|
|
9
|
+
* A segment position needs at least this many distinct values to be wildcarded.
|
|
10
|
+
* Two siblings are as likely to be two distinct pages as one template with two
|
|
11
|
+
* instances, so the floor is three.
|
|
12
|
+
*/
|
|
13
|
+
const WILDCARD_DISTINCT = 3;
|
|
14
|
+
/**
|
|
15
|
+
* The signal that separates an identifier from a section name: **fan-out**.
|
|
16
|
+
*
|
|
17
|
+
* Cardinality alone does not work, and getting this wrong is visible on real
|
|
18
|
+
* sites. On nodejs.org, "/en/{blog,download,learn,about}" has only a handful of
|
|
19
|
+
* distinct values, so a pure count threshold wildcarded it and merged 1,054
|
|
20
|
+
* blog posts, download pages and API docs into one meaningless "/en/*\/*\/*"
|
|
21
|
+
* template.
|
|
22
|
+
*
|
|
23
|
+
* A section name is shared by many URLs (blog → 900 pages); an identifier
|
|
24
|
+
* belongs to one (v04.3 → 1 page). So a segment is a wildcard when its values
|
|
25
|
+
* each account for very few URLs, and stays literal when each value heads a
|
|
26
|
+
* substantial subtree — regardless of how many there are.
|
|
27
|
+
*/
|
|
28
|
+
const MAX_MEAN_FANOUT = 2.5;
|
|
29
|
+
/**
|
|
30
|
+
* The first path segment is the site's own taxonomy — "categories", "products",
|
|
31
|
+
* "info" — and collapsing it produces the useless pattern "/*". It only gets
|
|
32
|
+
* wildcarded on a clear id explosion.
|
|
33
|
+
*/
|
|
34
|
+
const WILDCARD_DISTINCT_ROOT = 20;
|
|
35
|
+
const ID_LIKE = /^(\d+|[0-9a-f]{8,}|[0-9a-f-]{16,}|p\d+|sku[-_]?\w+)$/i;
|
|
36
|
+
/**
|
|
37
|
+
* Route vocabulary — segments that name a *kind* of page, never an instance.
|
|
38
|
+
*
|
|
39
|
+
* Fan-out alone misreads these on a small URL list. Given eight URLs under
|
|
40
|
+
* /ecommerce/, the segments {page, product, cart, checkout, my-account} average
|
|
41
|
+
* 1.6 URLs each, which looks exactly like a set of identifiers — so the
|
|
42
|
+
* classifier collapsed paginated listings and product detail pages into one
|
|
43
|
+
* "/ecommerce/*\/*" template and proposed sampling them as if they were the
|
|
44
|
+
* same page type. On the full inventory the fan-out for "product" would be
|
|
45
|
+
* large and the heuristic would work, but a plan should not be wrong just
|
|
46
|
+
* because the input list is short.
|
|
47
|
+
*/
|
|
48
|
+
const ROUTE_WORDS = new Set([
|
|
49
|
+
"page", "pages", "product", "products", "category", "categories", "collection",
|
|
50
|
+
"collections", "cart", "basket", "checkout", "account", "my-account", "login",
|
|
51
|
+
"signin", "register", "search", "tag", "tags", "author", "feed", "blog", "news",
|
|
52
|
+
"article", "articles", "post", "posts", "info", "about", "help", "support",
|
|
53
|
+
"shop", "store", "browse", "dept", "department", "item", "items", "sku",
|
|
54
|
+
]);
|
|
55
|
+
/**
|
|
56
|
+
* A content slug: hyphenated and long enough to be a title rather than a route.
|
|
57
|
+
* "adrienne-trek-jacket" is an instance; "my-account" is a route.
|
|
58
|
+
*/
|
|
59
|
+
function looksLikeSlug(value) {
|
|
60
|
+
if (!value.includes("-"))
|
|
61
|
+
return false;
|
|
62
|
+
const words = value.split("-").length;
|
|
63
|
+
return value.length >= 14 || words >= 3;
|
|
64
|
+
}
|
|
65
|
+
function parseUrl(raw) {
|
|
66
|
+
let url;
|
|
67
|
+
try {
|
|
68
|
+
url = new URL(raw);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
const segments = url.pathname.split("/").filter(Boolean);
|
|
74
|
+
const keys = [...url.searchParams.keys()]
|
|
75
|
+
.filter((k) => !TRACKING_PARAMS.test(k))
|
|
76
|
+
.map((k) => k.toLowerCase())
|
|
77
|
+
.sort();
|
|
78
|
+
return { raw, segments, querySig: [...new Set(keys)].join("&") };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Wildcard a segment when its values are identifiers rather than taxonomy.
|
|
82
|
+
* Cardinality alone is the main signal; an id-shaped majority is enough on its
|
|
83
|
+
* own, since "/p/12345" and "/p/12346" are the same page template even when
|
|
84
|
+
* only two exist.
|
|
85
|
+
*/
|
|
86
|
+
function shouldWildcard(depth, values) {
|
|
87
|
+
const distinct = new Set(values);
|
|
88
|
+
if (distinct.size < 2)
|
|
89
|
+
return false;
|
|
90
|
+
// Numeric, hash-shaped and long-slug values are identifiers whatever their
|
|
91
|
+
// fan-out; route vocabulary never is.
|
|
92
|
+
const values_ = [...distinct].map((v) => v.toLowerCase());
|
|
93
|
+
const idLike = values_.filter((v) => ID_LIKE.test(v) || looksLikeSlug(v)).length;
|
|
94
|
+
if (idLike / distinct.size > 0.6)
|
|
95
|
+
return true;
|
|
96
|
+
if (values_.every((v) => ROUTE_WORDS.has(v)))
|
|
97
|
+
return false;
|
|
98
|
+
if (depth === 0 && distinct.size < WILDCARD_DISTINCT_ROOT)
|
|
99
|
+
return false;
|
|
100
|
+
if (distinct.size < WILDCARD_DISTINCT)
|
|
101
|
+
return false;
|
|
102
|
+
return values.length / distinct.size <= MAX_MEAN_FANOUT;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Recursive descent over path segments.
|
|
106
|
+
*
|
|
107
|
+
* At each depth, URLs that end here form their own pattern, and the rest are
|
|
108
|
+
* grouped by their next segment — wildcarded together when that segment looks
|
|
109
|
+
* like an identifier, kept apart when it looks like a section name. Recursion
|
|
110
|
+
* (rather than one global pass per depth) is what keeps "/categories/*" and
|
|
111
|
+
* "/products/*" separate instead of collapsing both into "/*\/*".
|
|
112
|
+
*/
|
|
113
|
+
function descend(urls, depth, prefix, out) {
|
|
114
|
+
const terminal = urls.filter((u) => u.segments.length === depth);
|
|
115
|
+
const deeper = urls.filter((u) => u.segments.length > depth);
|
|
116
|
+
if (terminal.length > 0) {
|
|
117
|
+
const key = "/" + prefix.join("/");
|
|
118
|
+
for (const u of terminal) {
|
|
119
|
+
const full = u.querySig ? `${key}?${u.querySig}` : key;
|
|
120
|
+
const bucket = out.get(full);
|
|
121
|
+
if (bucket)
|
|
122
|
+
bucket.push(u);
|
|
123
|
+
else
|
|
124
|
+
out.set(full, [u]);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (deeper.length === 0)
|
|
128
|
+
return;
|
|
129
|
+
if (shouldWildcard(depth, deeper.map((u) => u.segments[depth]))) {
|
|
130
|
+
descend(deeper, depth + 1, [...prefix, "*"], out);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const groups = new Map();
|
|
134
|
+
for (const u of deeper) {
|
|
135
|
+
const token = u.segments[depth];
|
|
136
|
+
const bucket = groups.get(token);
|
|
137
|
+
if (bucket)
|
|
138
|
+
bucket.push(u);
|
|
139
|
+
else
|
|
140
|
+
groups.set(token, [u]);
|
|
141
|
+
}
|
|
142
|
+
for (const [token, group] of groups) {
|
|
143
|
+
descend(group, depth + 1, [...prefix, token], out);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Human labels for common commerce and content shapes.
|
|
148
|
+
*
|
|
149
|
+
* Deliberately conservative: an unrecognised pattern is labelled by its path
|
|
150
|
+
* rather than guessed at, because a wrong label in an executive report is
|
|
151
|
+
* worse than a literal one.
|
|
152
|
+
*/
|
|
153
|
+
function labelFor(pattern) {
|
|
154
|
+
const [path, query] = pattern.split("?");
|
|
155
|
+
const p = path.toLowerCase();
|
|
156
|
+
const depth = path.split("/").filter(Boolean).length;
|
|
157
|
+
const wildcards = (path.match(/\*/g) ?? []).length;
|
|
158
|
+
const paginated = query ? ` (${query.includes("p") || query.includes("page") ? "paginated" : "filtered"})` : "";
|
|
159
|
+
if (path === "/")
|
|
160
|
+
return "Homepage";
|
|
161
|
+
if (/(^|\/)(cart|basket|bag)(\/|$)/.test(p))
|
|
162
|
+
return "Cart";
|
|
163
|
+
if (/(^|\/)(checkout|payment)(\/|$)/.test(p))
|
|
164
|
+
return "Checkout";
|
|
165
|
+
if (/(^|\/)(search|s|find)(\/|$)/.test(p))
|
|
166
|
+
return "Search results";
|
|
167
|
+
if (/(^|\/)(store-locator|stores|locations|find-a-store)(\/|$)/.test(p))
|
|
168
|
+
return "Store locator";
|
|
169
|
+
if (/(^|\/)(account|my-account|profile|orders|wishlist)(\/|$)/.test(p))
|
|
170
|
+
return "Account";
|
|
171
|
+
if (/(^|\/)(login|signin|sign-in|register|signup)(\/|$)/.test(p))
|
|
172
|
+
return "Login / register";
|
|
173
|
+
if (/(^|\/)(product|products|p|item|items|sku|dp)(\/|$)/.test(p))
|
|
174
|
+
return `PDP (product)${paginated}`;
|
|
175
|
+
if (/(^|\/)(blog|news|articles|stories|posts)(\/|$)/.test(p))
|
|
176
|
+
return `Content / article${paginated}`;
|
|
177
|
+
if (/(^|\/)(info|about|help|faq|support|legal|privacy|terms|policies|customer-service)(\/|$)/.test(p))
|
|
178
|
+
return `Info / static${paginated}`;
|
|
179
|
+
if (/(^|\/)(categories|category|c|collections|shop|browse|dept|department)(\/|$)/.test(p)) {
|
|
180
|
+
const kind = wildcards >= 2 ? "subcategory" : "category";
|
|
181
|
+
return `PLP (${kind})${paginated}`;
|
|
182
|
+
}
|
|
183
|
+
if (wildcards > 0 && depth <= 2)
|
|
184
|
+
return `Listing${paginated}`;
|
|
185
|
+
return `${path}${paginated}`;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Sample size by population.
|
|
189
|
+
*
|
|
190
|
+
* Three is the ceiling because PSI is slow and quota is finite, and because
|
|
191
|
+
* variance between pages of one template is usually smaller than variance
|
|
192
|
+
* between templates — a fourth PDP tells you much less than a first Cart.
|
|
193
|
+
*/
|
|
194
|
+
function suggestSample(population) {
|
|
195
|
+
if (population <= 1)
|
|
196
|
+
return 1;
|
|
197
|
+
if (population <= 5)
|
|
198
|
+
return 2;
|
|
199
|
+
return 3;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Representatives, chosen for spread rather than at random.
|
|
203
|
+
*
|
|
204
|
+
* Shortest first: it is usually the canonical, most-linked instance of the
|
|
205
|
+
* template. Then the longest and a middle one, because URL length correlates
|
|
206
|
+
* with depth and with how much content the page carries, and a template's
|
|
207
|
+
* worst page is more often its longest.
|
|
208
|
+
*/
|
|
209
|
+
function pickCandidates(urls, count) {
|
|
210
|
+
const sorted = [...urls].sort((a, b) => a.length - b.length || a.localeCompare(b));
|
|
211
|
+
if (sorted.length <= count)
|
|
212
|
+
return sorted;
|
|
213
|
+
const picks = [sorted[0]];
|
|
214
|
+
if (count >= 2)
|
|
215
|
+
picks.push(sorted[sorted.length - 1]);
|
|
216
|
+
if (count >= 3)
|
|
217
|
+
picks.push(sorted[Math.floor(sorted.length / 2)]);
|
|
218
|
+
for (let i = 1; picks.length < count && i < sorted.length; i++) {
|
|
219
|
+
if (!picks.includes(sorted[i]))
|
|
220
|
+
picks.push(sorted[i]);
|
|
221
|
+
}
|
|
222
|
+
return picks.slice(0, count);
|
|
223
|
+
}
|
|
224
|
+
function slugify(pattern) {
|
|
225
|
+
return (pattern
|
|
226
|
+
.replace(/[?&=]/g, "-")
|
|
227
|
+
.replace(/\*/g, "wild")
|
|
228
|
+
.replace(/[^a-z0-9]+/gi, "-")
|
|
229
|
+
.replace(/^-+|-+$/g, "")
|
|
230
|
+
.toLowerCase() || "root");
|
|
231
|
+
}
|
|
232
|
+
export function classifyUrls(rawUrls, options = {}) {
|
|
233
|
+
const { minTemplateSize = 1 } = options;
|
|
234
|
+
const parsed = [];
|
|
235
|
+
let skipped = 0;
|
|
236
|
+
for (const raw of rawUrls) {
|
|
237
|
+
const p = parseUrl(raw);
|
|
238
|
+
if (p)
|
|
239
|
+
parsed.push(p);
|
|
240
|
+
else
|
|
241
|
+
skipped++;
|
|
242
|
+
}
|
|
243
|
+
const buckets = new Map();
|
|
244
|
+
descend(parsed, 0, [], buckets);
|
|
245
|
+
const templates = [];
|
|
246
|
+
for (const [pattern, group] of buckets) {
|
|
247
|
+
if (group.length < minTemplateSize)
|
|
248
|
+
continue;
|
|
249
|
+
const urls = group.map((g) => g.raw);
|
|
250
|
+
const suggested = suggestSample(urls.length);
|
|
251
|
+
templates.push({
|
|
252
|
+
id: slugify(pattern),
|
|
253
|
+
label: labelFor(pattern),
|
|
254
|
+
pattern,
|
|
255
|
+
urlCount: urls.length,
|
|
256
|
+
suggestedSample: suggested,
|
|
257
|
+
candidates: pickCandidates(urls, suggested),
|
|
258
|
+
auditable: true,
|
|
259
|
+
anySessionGated: urls.some(isSessionGated),
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
// Biggest templates first: a reader scanning the plan should see the shapes
|
|
263
|
+
// that dominate the site before the long tail of one-off pages.
|
|
264
|
+
templates.sort((a, b) => b.urlCount - a.urlCount || a.pattern.localeCompare(b.pattern));
|
|
265
|
+
return { templates, skipped };
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=urlClassifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urlClassifier.js","sourceRoot":"","sources":["../../src/utils/urlClassifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AA+ChD;;;;GAIG;AACH,MAAM,eAAe,GAAG,mGAAmG,CAAC;AAE5H;;;;GAIG;AACH,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAE5B;;;;;;;;;;;;;GAaG;AACH,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B;;;;GAIG;AACH,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAElC,MAAM,OAAO,GAAG,uDAAuD,CAAC;AAExE;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY;IAC9E,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO;IAC7E,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAC/E,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS;IAC1E,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK;CACxE,CAAC,CAAC;AAEH;;;GAGG;AACH,SAAS,aAAa,CAAC,KAAa;IAClC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,OAAO,KAAK,CAAC,MAAM,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IAC3B,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;SACtC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SACvC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SAC3B,IAAI,EAAE,CAAC;IACV,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACnE,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,KAAa,EAAE,MAAgB;IACrD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAEpC,2EAA2E;IAC3E,sCAAsC;IACtC,MAAM,OAAO,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACjF,IAAI,MAAM,GAAG,QAAQ,CAAC,IAAI,GAAG,GAAG;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAE3D,IAAI,KAAK,KAAK,CAAC,IAAI,QAAQ,CAAC,IAAI,GAAG,sBAAsB;QAAE,OAAO,KAAK,CAAC;IACxE,IAAI,QAAQ,CAAC,IAAI,GAAG,iBAAiB;QAAE,OAAO,KAAK,CAAC;IAEpD,OAAO,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,IAAI,IAAI,eAAe,CAAC;AAC1D,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,OAAO,CACd,IAAiB,EACjB,KAAa,EACb,MAAgB,EAChB,GAA6B;IAE7B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;IAE7D,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;YACvD,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,MAAM;gBAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;gBACtB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEhC,IAAI,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,OAAO,CAAC,MAAM,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC9C,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,MAAM;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;YACtB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC;IACD,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QACpC,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,QAAQ,CAAC,OAAe;IAC/B,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IACrD,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IACnD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAEhH,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,UAAU,CAAC;IACpC,IAAI,+BAA+B,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC3D,IAAI,gCAAgC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,UAAU,CAAC;IAChE,IAAI,6BAA6B,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,gBAAgB,CAAC;IACnE,IAAI,2DAA2D,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,eAAe,CAAC;IAChG,IAAI,0DAA0D,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzF,IAAI,oDAAoD,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,kBAAkB,CAAC;IAC5F,IAAI,oDAAoD,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,gBAAgB,SAAS,EAAE,CAAC;IACrG,IAAI,gDAAgD,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,oBAAoB,SAAS,EAAE,CAAC;IACrG,IAAI,yFAAyF,CAAC,IAAI,CAAC,CAAC,CAAC;QACnG,OAAO,gBAAgB,SAAS,EAAE,CAAC;IACrC,IAAI,6EAA6E,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1F,MAAM,IAAI,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC;QACzD,OAAO,QAAQ,IAAI,IAAI,SAAS,EAAE,CAAC;IACrC,CAAC;IACD,IAAI,SAAS,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,UAAU,SAAS,EAAE,CAAC;IAC9D,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,CAAC;AAC/B,CAAC;AAED;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,UAAkB;IACvC,IAAI,UAAU,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAC9B,IAAI,UAAU,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,cAAc,CAAC,IAAc,EAAE,KAAa;IACnD,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,IAAI,MAAM,CAAC,MAAM,IAAI,KAAK;QAAE,OAAO,MAAM,CAAC;IAC1C,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,KAAK,IAAI,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACtD,IAAI,KAAK,IAAI,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/D,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,OAAO,CAAC,OAAe;IAC9B,OAAO,CACL,OAAO;SACJ,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;SAC5B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,WAAW,EAAE,IAAI,MAAM,CAC3B,CAAC;AACJ,CAAC;AAOD,MAAM,UAAU,YAAY,CAC1B,OAAiB,EACjB,UAA2B,EAAE;IAE7B,MAAM,EAAE,eAAe,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;IAExC,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;;YACjB,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC/C,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IAEhC,MAAM,SAAS,GAAkB,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;QACvC,IAAI,KAAK,CAAC,MAAM,GAAG,eAAe;YAAE,SAAS;QAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,SAAS,CAAC,IAAI,CAAC;YACb,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC;YACpB,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC;YACxB,OAAO;YACP,QAAQ,EAAE,IAAI,CAAC,MAAM;YACrB,eAAe,EAAE,SAAS;YAC1B,UAAU,EAAE,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC;YAC3C,SAAS,EAAE,IAAI;YACf,eAAe,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;SAC3C,CAAC,CAAC;IACL,CAAC;IAED,4EAA4E;IAC5E,gEAAgE;IAChE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACxF,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC"}
|