@erdemtuna/doc-review 0.9.0 → 0.11.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 +58 -222
- package/{src → lib}/SKILL.md +5 -2
- package/lib/anchor-text.js +155 -0
- package/lib/atomic-write.js +54 -0
- package/lib/changes-controller.js +184 -0
- package/lib/chrome-api.js +78 -0
- package/lib/chrome-client.js +1700 -0
- package/lib/chrome-session.js +73 -0
- package/lib/chrome.html +53 -0
- package/lib/cli.js +255 -0
- package/lib/click-target.js +28 -0
- package/lib/comment-anchor.js +23 -0
- package/lib/comment-target.js +164 -0
- package/lib/comments-controller.js +109 -0
- package/lib/contextual-controller.js +33 -0
- package/lib/contracts/feedback.js +1 -0
- package/lib/contracts/frame.js +7 -0
- package/lib/contracts/history.js +1 -0
- package/lib/contracts/index.js +2 -0
- package/lib/contracts/page.js +23 -0
- package/lib/controller-store.js +96 -0
- package/lib/document-execution.js +115 -0
- package/lib/edit-limits.js +24 -0
- package/lib/editing.js +107 -0
- package/lib/execution-client.js +19 -0
- package/lib/feedback-controller.js +113 -0
- package/lib/feedback-panel-controller.js +161 -0
- package/lib/frame-channel.js +42 -0
- package/lib/frame-controller.js +313 -0
- package/lib/frame-host.js +136 -0
- package/lib/frame-policy.js +50 -0
- package/lib/history-client.js +112 -0
- package/lib/history-coordinator.js +217 -0
- package/lib/history-policy.js +43 -0
- package/lib/history-server.js +464 -0
- package/lib/html-transform.js +52 -0
- package/lib/icons.js +325 -0
- package/{src → lib}/markdown.js +25 -26
- package/lib/paths.js +83 -0
- package/lib/poll-transport.js +220 -0
- package/lib/positioning.js +97 -0
- package/lib/recovery-controller.js +123 -0
- package/lib/review-controller.js +93 -0
- package/lib/review-mode.js +66 -0
- package/lib/revision-diff.js +482 -0
- package/lib/revision-schema.js +235 -0
- package/lib/revision-store.js +190 -0
- package/lib/save-controller.js +303 -0
- package/lib/sdk.js +2629 -0
- package/lib/semantic-snapshot.js +268 -0
- package/lib/serialize.js +32 -0
- package/lib/server-entry.js +26 -0
- package/lib/server-lock.js +109 -0
- package/lib/server.js +1501 -0
- package/lib/setup-guidance.js +119 -0
- package/{src → lib}/setup.js +44 -55
- package/lib/state.js +733 -0
- package/lib/toolbar-controller.js +32 -0
- package/lib/ui/THIRD_PARTY_NOTICES.md +1254 -0
- package/lib/ui/chrome.css +4881 -0
- package/lib/ui/chrome.js +52 -0
- package/lib/view-identity.js +112 -0
- package/package.json +50 -14
- package/src/anchor-text.js +0 -160
- package/src/atomic-write.js +0 -53
- package/src/chrome-client.js +0 -2747
- package/src/chrome-session.js +0 -85
- package/src/chrome.css +0 -652
- package/src/chrome.html +0 -196
- package/src/cli.js +0 -271
- package/src/click-target.js +0 -26
- package/src/comment-anchor.js +0 -22
- package/src/comment-target.js +0 -164
- package/src/comparison-view.js +0 -337
- package/src/document-execution.js +0 -103
- package/src/edit-limits.js +0 -23
- package/src/editing.js +0 -99
- package/src/execution-client.js +0 -63
- package/src/frame-channel.js +0 -44
- package/src/frame-policy.js +0 -54
- package/src/history-client.js +0 -104
- package/src/history-coordinator.js +0 -186
- package/src/history-policy.js +0 -43
- package/src/history-server.js +0 -463
- package/src/html-transform.js +0 -62
- package/src/icons.js +0 -251
- package/src/paths.js +0 -91
- package/src/poll-transport.js +0 -222
- package/src/positioning.js +0 -107
- package/src/review-mode.js +0 -59
- package/src/revision-diff.js +0 -440
- package/src/revision-schema.js +0 -219
- package/src/revision-store.js +0 -177
- package/src/sdk.js +0 -2607
- package/src/semantic-snapshot.js +0 -230
- package/src/serialize.js +0 -32
- package/src/server-entry.js +0 -26
- package/src/server-lock.js +0 -101
- package/src/server.js +0 -1466
- package/src/setup-guidance.js +0 -128
- package/src/state.js +0 -732
- package/src/view-identity.js +0 -99
- /package/{src → lib}/document-trust.js +0 -0
package/src/view-identity.js
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
const MAX_TABS = 32;
|
|
2
|
-
const MAX_ID = 256;
|
|
3
|
-
const unknown = (reason) => ({ version: 1, status: "unverified", tabs: [], reason });
|
|
4
|
-
|
|
5
|
-
export function normalizeView(value) {
|
|
6
|
-
if (value === undefined || value === null) return unknown("View identity was not recorded.");
|
|
7
|
-
const invalid = () => { throw Object.assign(new Error("Invalid captured view identity."), { code: "INVALID_REVISION", status: 400 }); };
|
|
8
|
-
if (value.version !== 1 || !["identified", "unverified"].includes(value.status) ||
|
|
9
|
-
!Array.isArray(value.tabs) || value.tabs.length > MAX_TABS) invalid();
|
|
10
|
-
if (value.status === "unverified") {
|
|
11
|
-
if (value.tabs.length || (value.reason !== undefined && (typeof value.reason !== "string" || value.reason.length > 500))) invalid();
|
|
12
|
-
return unknown(value.reason || "View identity could not be verified.");
|
|
13
|
-
}
|
|
14
|
-
if (!value.tabs.length) invalid();
|
|
15
|
-
const groups = new Set();
|
|
16
|
-
const tabs = value.tabs.map((tab) => {
|
|
17
|
-
if (!tab || typeof tab !== "object") invalid();
|
|
18
|
-
for (const key of ["groupId", "tabId", "panelId", "label"]) {
|
|
19
|
-
if (typeof tab[key] !== "string" || !tab[key] || tab[key].length > MAX_ID) invalid();
|
|
20
|
-
}
|
|
21
|
-
if (groups.has(tab.groupId)) invalid();
|
|
22
|
-
groups.add(tab.groupId);
|
|
23
|
-
return { groupId: tab.groupId, tabId: tab.tabId, panelId: tab.panelId, label: tab.label };
|
|
24
|
-
}).sort((a, b) => a.groupId.localeCompare(b.groupId));
|
|
25
|
-
return { version: 1, status: "identified", tabs };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function viewKey(view) {
|
|
29
|
-
const normalized = normalizeView(view);
|
|
30
|
-
return JSON.stringify([normalized.status, normalized.tabs.map(({ groupId, tabId, panelId }) => [groupId, tabId, panelId])]);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function sameObservedView(before, after) {
|
|
34
|
-
return viewKey(before) === viewKey(after);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function compareCapturedViews(before, after) {
|
|
38
|
-
const left = normalizeView(before);
|
|
39
|
-
const right = normalizeView(after);
|
|
40
|
-
if (left.status === "identified") {
|
|
41
|
-
if (right.status === "identified" && sameObservedView(left, right)) {
|
|
42
|
-
return { status: "matched", message: `Matching visible view: ${left.tabs.map((tab) => tab.label).join(" / ")}.` };
|
|
43
|
-
}
|
|
44
|
-
return {
|
|
45
|
-
status: "mismatch",
|
|
46
|
-
message: `Return to ${left.tabs.map((tab) => tab.label).join(" / ")} to capture the result.${right.status === "unverified" ? " The current tab identity could not be verified." : ""}`,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
return { status: "unverified", message: "Visible content only; matching view not verified." };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function observeView(document) {
|
|
53
|
-
const started = Date.now();
|
|
54
|
-
let visited = 0;
|
|
55
|
-
let limited = false;
|
|
56
|
-
const visible = (element) => {
|
|
57
|
-
for (let node = element; node; node = node.parentElement) {
|
|
58
|
-
if (++visited > 5000 || Date.now() - started > 500) {
|
|
59
|
-
limited = true;
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
if (node.hidden || node.getAttribute("aria-hidden") === "true" || node.hasAttribute("data-eh-ui")) return false;
|
|
63
|
-
const style = document.defaultView.getComputedStyle(node);
|
|
64
|
-
if (style.display === "none" || style.visibility === "hidden") return false;
|
|
65
|
-
}
|
|
66
|
-
return true;
|
|
67
|
-
};
|
|
68
|
-
const uniqueId = (element) => {
|
|
69
|
-
if (!element?.id || element.id.length > MAX_ID) return false;
|
|
70
|
-
const escaped = element.id.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/[\n\r\f]/g, "");
|
|
71
|
-
return document.querySelectorAll(`[id="${escaped}"]`).length === 1;
|
|
72
|
-
};
|
|
73
|
-
const candidates = document.querySelectorAll('[role="tablist"]');
|
|
74
|
-
if (candidates.length > MAX_TABS) return unknown("Too many tab groups to identify reliably.");
|
|
75
|
-
const groups = [...candidates].filter(visible);
|
|
76
|
-
if (limited) return unknown("View identity observation exceeded its limits.");
|
|
77
|
-
if (!groups.length) return unknown("No reliably identifiable tab groups were found.");
|
|
78
|
-
if (groups.length > MAX_TABS) return unknown("Too many tab groups to identify reliably.");
|
|
79
|
-
const tabs = [];
|
|
80
|
-
for (const group of groups) {
|
|
81
|
-
const members = [...group.querySelectorAll('[role="tab"]')].filter((tab) => tab.closest('[role="tablist"]') === group);
|
|
82
|
-
if (members.length > 128 || Date.now() - started > 500) return unknown("View identity observation exceeded its limits.");
|
|
83
|
-
const selected = members.filter((tab) => tab.getAttribute("aria-selected") === "true");
|
|
84
|
-
if (selected.length !== 1) return unknown("A tab group does not have exactly one selected tab.");
|
|
85
|
-
const tab = selected[0];
|
|
86
|
-
const panelId = tab.getAttribute("aria-controls");
|
|
87
|
-
const panel = panelId && document.getElementById(panelId);
|
|
88
|
-
if (!visible(tab) || !uniqueId(tab) || !uniqueId(panel) || panel.getAttribute("role") !== "tabpanel" || !visible(panel)) {
|
|
89
|
-
return unknown("Selected tabs and visible panels do not have unique stable identifiers.");
|
|
90
|
-
}
|
|
91
|
-
// A complete set of authored tab IDs identifies an otherwise unnamed tablist.
|
|
92
|
-
if (!members.length || members.some((member) => !uniqueId(member))) return unknown("Tab identifiers are incomplete.");
|
|
93
|
-
const groupId = uniqueId(group) ? `id:${group.id}` : `tabs:${JSON.stringify(members.map((member) => member.id).sort())}`;
|
|
94
|
-
if (groupId.length > MAX_ID) return unknown("Tab group identity exceeds the capture limit.");
|
|
95
|
-
const label = (tab.getAttribute("aria-label") || tab.textContent || tab.id).replace(/\s+/g, " ").trim().slice(0, MAX_ID);
|
|
96
|
-
tabs.push({ groupId, tabId: tab.id, panelId, label: label || tab.id });
|
|
97
|
-
}
|
|
98
|
-
return normalizeView({ version: 1, status: "identified", tabs });
|
|
99
|
-
}
|
|
File without changes
|