@olomonhelpdesk2/helpdesk 0.1.18 → 0.1.19
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/helpdesk-capture.mjs +611 -130
- package/helpdesk-seed.mjs +7 -1
- package/helpdesk.mjs +38 -9
- package/package.json +1 -1
package/helpdesk-seed.mjs
CHANGED
|
@@ -1001,8 +1001,14 @@ var CAPTURE_CONTRACT = {
|
|
|
1001
1001
|
timezone: "UTC",
|
|
1002
1002
|
/**
|
|
1003
1003
|
* Injected before every shot. Necessary, not sufficient — see above.
|
|
1004
|
+
*
|
|
1005
|
+
* Every CSS animation ends at once, on its last frame, rather than being
|
|
1006
|
+
* removed. An entrance starts its element at opacity 0 and keeps the last
|
|
1007
|
+
* frame it animates to, and `animation: none` left that element at opacity
|
|
1008
|
+
* 0, so a site's hero was blank in every frame. One that loops ends after a
|
|
1009
|
+
* single instant pass, back at its element's own style.
|
|
1004
1010
|
*/
|
|
1005
|
-
motionOff: "*,*::before,*::after{animation:
|
|
1011
|
+
motionOff: "*,*::before,*::after{animation-duration:0s!important;animation-delay:0s!important;animation-iteration-count:1!important;transition:none!important;caret-color:transparent!important}",
|
|
1006
1012
|
/**
|
|
1007
1013
|
* What an app uses to leave its own floating widgets out of the pictures.
|
|
1008
1014
|
*
|
package/helpdesk.mjs
CHANGED
|
@@ -148,6 +148,34 @@ function depth(path) {
|
|
|
148
148
|
return path === "/" ? 0 : path.split("/").filter(Boolean).length;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
// core/discovery/apps.ts
|
|
152
|
+
var ROOT_SHARE = 0.8;
|
|
153
|
+
function appRoot(routes) {
|
|
154
|
+
const screens = documentable(routes);
|
|
155
|
+
const root = [];
|
|
156
|
+
for (; ; ) {
|
|
157
|
+
const counts = /* @__PURE__ */ new Map();
|
|
158
|
+
for (const route of screens) {
|
|
159
|
+
const segments = staticSegments(route.path);
|
|
160
|
+
const next = segments[root.length];
|
|
161
|
+
if (next && root.every((segment2, index) => segments[index] === segment2)) counts.set(next, (counts.get(next) ?? 0) + 1);
|
|
162
|
+
}
|
|
163
|
+
const [segment, count = 0] = [...counts].sort((a, b) => b[1] - a[1])[0] ?? [];
|
|
164
|
+
if (!segment || count < Math.max(3, screens.length * ROOT_SHARE)) return root;
|
|
165
|
+
root.push(segment);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function belowAppRoot(path, root) {
|
|
169
|
+
const segments = path.split("/").filter(Boolean);
|
|
170
|
+
return root.length && root.every((segment, index) => segments[index] === segment) ? segments.slice(root.length) : segments;
|
|
171
|
+
}
|
|
172
|
+
function staticSegments(path) {
|
|
173
|
+
return path.split("/").filter((segment) => segment && !segment.startsWith("["));
|
|
174
|
+
}
|
|
175
|
+
function documentable(routes) {
|
|
176
|
+
return routes.filter((route) => !route.skipped);
|
|
177
|
+
}
|
|
178
|
+
|
|
151
179
|
// core/discovery/article-plan.ts
|
|
152
180
|
var MONEY_OR_ACCESS = /* @__PURE__ */ new Set([
|
|
153
181
|
"billing",
|
|
@@ -226,9 +254,9 @@ function slugFor(path) {
|
|
|
226
254
|
const segments = path.split("/").filter(Boolean).filter((segment) => !segment.startsWith("["));
|
|
227
255
|
return segments.length ? segments.join("/") : "overview";
|
|
228
256
|
}
|
|
229
|
-
function titleFor(route) {
|
|
230
|
-
const segments = route.path
|
|
231
|
-
if (!segments.length) return "Getting around";
|
|
257
|
+
function titleFor(route, root) {
|
|
258
|
+
const segments = belowAppRoot(route.path, root).filter((s) => !s.startsWith("["));
|
|
259
|
+
if (!segments.length) return route.params.length ? "Working with a record" : "Getting around";
|
|
232
260
|
const words = segments[segments.length - 1].replace(/[-_]/g, " ");
|
|
233
261
|
const subject = words.charAt(0).toUpperCase() + words.slice(1);
|
|
234
262
|
if (!route.params.length) return subject;
|
|
@@ -280,6 +308,7 @@ function buildArticlePlan(options) {
|
|
|
280
308
|
}
|
|
281
309
|
}
|
|
282
310
|
let covered = 0;
|
|
311
|
+
const root = appRoot(options.routes);
|
|
283
312
|
const needs = [...merged.entries()].map(([slug, group], index) => {
|
|
284
313
|
const rank = index + 1;
|
|
285
314
|
const claimed = [group.entry.route.path, ...group.routes.slice(1) ?? []].map((path) => options.documented?.[path]).find(Boolean);
|
|
@@ -287,7 +316,7 @@ function buildArticlePlan(options) {
|
|
|
287
316
|
if (already) covered += 1;
|
|
288
317
|
return {
|
|
289
318
|
slug,
|
|
290
|
-
title: group.title ?? titleFor(group.entry.route),
|
|
319
|
+
title: group.title ?? titleFor(group.entry.route, root),
|
|
291
320
|
route: group.entry.route.path,
|
|
292
321
|
...group.routes.length > 1 ? { alsoCovers: group.routes.slice(1) } : {},
|
|
293
322
|
tier: tierFor(rank, merged.size),
|
|
@@ -951,8 +980,8 @@ function readProduct(routes, options) {
|
|
|
951
980
|
}
|
|
952
981
|
return found;
|
|
953
982
|
};
|
|
954
|
-
const
|
|
955
|
-
const total = Math.min(
|
|
983
|
+
const documentable2 = routes.filter((route) => !route.skipped);
|
|
984
|
+
const total = Math.min(documentable2.length, maxScreens);
|
|
956
985
|
const reading = { how: "source", commit: options.commit ?? null };
|
|
957
986
|
let done = 0;
|
|
958
987
|
let withFacts = 0;
|
|
@@ -984,10 +1013,10 @@ function hasAnything(facts) {
|
|
|
984
1013
|
);
|
|
985
1014
|
}
|
|
986
1015
|
function describeReading(routes) {
|
|
987
|
-
const
|
|
988
|
-
const read =
|
|
1016
|
+
const documentable2 = routes.filter((route) => !route.skipped);
|
|
1017
|
+
const read = documentable2.filter((route) => route.facts && hasAnything(route.facts));
|
|
989
1018
|
return {
|
|
990
|
-
screens:
|
|
1019
|
+
screens: documentable2.length,
|
|
991
1020
|
read: read.length,
|
|
992
1021
|
rendered: read.filter((route) => route.facts?.read?.how === "rendered").length,
|
|
993
1022
|
pathsOnly: read.length === 0
|