semantic-code-review 0.24.2__py3-none-any.whl
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.
- semantic_code_review/__init__.py +5 -0
- semantic_code_review/augment/__init__.py +3 -0
- semantic_code_review/augment/agents.py +95 -0
- semantic_code_review/augment/console.py +440 -0
- semantic_code_review/augment/extra_review.py +237 -0
- semantic_code_review/augment/fold_summary.py +447 -0
- semantic_code_review/augment/hunks.py +264 -0
- semantic_code_review/augment/mcp_server.py +156 -0
- semantic_code_review/augment/overview.py +233 -0
- semantic_code_review/augment/pass_.py +171 -0
- semantic_code_review/augment/pipeline.py +571 -0
- semantic_code_review/augment/progress.py +223 -0
- semantic_code_review/augment/prompts.py +93 -0
- semantic_code_review/augment/schemas.py +408 -0
- semantic_code_review/augment/tools.py +475 -0
- semantic_code_review/augment/trace_adapter.py +369 -0
- semantic_code_review/backends/__init__.py +95 -0
- semantic_code_review/backends/_cli_driver.py +571 -0
- semantic_code_review/backends/anthropic_sdk.py +56 -0
- semantic_code_review/backends/base.py +104 -0
- semantic_code_review/backends/claude_cli.py +421 -0
- semantic_code_review/backends/google_sdk.py +73 -0
- semantic_code_review/backends/openai_compat.py +42 -0
- semantic_code_review/cache/__init__.py +3 -0
- semantic_code_review/cache/store.py +87 -0
- semantic_code_review/cli/__init__.py +70 -0
- semantic_code_review/cli/_shared.py +157 -0
- semantic_code_review/cli/augment.py +74 -0
- semantic_code_review/cli/config_cmd.py +266 -0
- semantic_code_review/cli/fetch.py +33 -0
- semantic_code_review/cli/lint.py +27 -0
- semantic_code_review/cli/pr.py +98 -0
- semantic_code_review/cli/review.py +104 -0
- semantic_code_review/cli/runs_cmd.py +17 -0
- semantic_code_review/cli/show.py +19 -0
- semantic_code_review/cli/strip.py +20 -0
- semantic_code_review/config.py +563 -0
- semantic_code_review/config_template.py +154 -0
- semantic_code_review/fetch/__init__.py +61 -0
- semantic_code_review/fetch/anchor.py +244 -0
- semantic_code_review/fetch/github.py +229 -0
- semantic_code_review/fetch/github_comments.py +404 -0
- semantic_code_review/fetch/local.py +443 -0
- semantic_code_review/fetch/run_source.py +70 -0
- semantic_code_review/format/__init__.py +3 -0
- semantic_code_review/format/emit.py +163 -0
- semantic_code_review/format/lint.py +74 -0
- semantic_code_review/format/parse.py +574 -0
- semantic_code_review/format/sidecar.py +19 -0
- semantic_code_review/format/strip.py +20 -0
- semantic_code_review/git_ops.py +252 -0
- semantic_code_review/paths.py +61 -0
- semantic_code_review/review/__init__.py +3 -0
- semantic_code_review/review/comments.py +176 -0
- semantic_code_review/review/github.py +284 -0
- semantic_code_review/review/github_graphql.py +433 -0
- semantic_code_review/review/pr_flow.py +299 -0
- semantic_code_review/review/runner.py +407 -0
- semantic_code_review/review/server.py +1043 -0
- semantic_code_review/structural/__init__.py +41 -0
- semantic_code_review/structural/diff.py +102 -0
- semantic_code_review/structural/parse.py +330 -0
- semantic_code_review/structural/symbols.py +43 -0
- semantic_code_review/viewer/__init__.py +3 -0
- semantic_code_review/viewer/assets/annotations.ts +547 -0
- semantic_code_review/viewer/assets/boot.ts +273 -0
- semantic_code_review/viewer/assets/comment_store.ts +121 -0
- semantic_code_review/viewer/assets/comments.ts +624 -0
- semantic_code_review/viewer/assets/console.ts +426 -0
- semantic_code_review/viewer/assets/console_render.ts +213 -0
- semantic_code_review/viewer/assets/console_selection.ts +102 -0
- semantic_code_review/viewer/assets/data_store.ts +156 -0
- semantic_code_review/viewer/assets/file_rows.ts +49 -0
- semantic_code_review/viewer/assets/folds.ts +560 -0
- semantic_code_review/viewer/assets/index.html +62 -0
- semantic_code_review/viewer/assets/post_modal.ts +383 -0
- semantic_code_review/viewer/assets/progress.ts +138 -0
- semantic_code_review/viewer/assets/render.ts +937 -0
- semantic_code_review/viewer/assets/sidebar.ts +429 -0
- semantic_code_review/viewer/assets/sse.ts +78 -0
- semantic_code_review/viewer/assets/text_highlight.ts +215 -0
- semantic_code_review/viewer/assets/types.d.ts +388 -0
- semantic_code_review/viewer/assets/vendor/LICENSE +29 -0
- semantic_code_review/viewer/assets/vendor/VENDOR.md +55 -0
- semantic_code_review/viewer/assets/vendor/github-dark.min.css +10 -0
- semantic_code_review/viewer/assets/vendor/github.min.css +10 -0
- semantic_code_review/viewer/assets/vendor/highlight.min.js +1244 -0
- semantic_code_review/viewer/assets/vendor/mermaid.LICENSE +21 -0
- semantic_code_review/viewer/assets/vendor/mermaid.min.js +3587 -0
- semantic_code_review/viewer/assets/vendor/refresh.sh +65 -0
- semantic_code_review/viewer/assets/viewer.css +1202 -0
- semantic_code_review/viewer/assets/viewer.js +10588 -0
- semantic_code_review/viewer/build_json.py +546 -0
- semantic_code_review/viewer/hunk_layout.py +471 -0
- semantic_code_review-0.24.2.dist-info/METADATA +348 -0
- semantic_code_review-0.24.2.dist-info/RECORD +100 -0
- semantic_code_review-0.24.2.dist-info/WHEEL +5 -0
- semantic_code_review-0.24.2.dist-info/entry_points.txt +2 -0
- semantic_code_review-0.24.2.dist-info/licenses/LICENSE +21 -0
- semantic_code_review-0.24.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Console selection resolution — "ask about *this*".
|
|
2
|
+
//
|
|
3
|
+
// Slice 4 (ADR 0002): turn a browser text selection into a structured
|
|
4
|
+
// hint the console can fold into a turn. We walk the selection's anchor
|
|
5
|
+
// up the rendered diff DOM, reusing the same `.cell-lineno` / `.hunk` /
|
|
6
|
+
// `.file` resolution the comment gutter uses (`comments.ts`), and
|
|
7
|
+
// classify the selection as code / comment / plain:
|
|
8
|
+
//
|
|
9
|
+
// - code — inside a diff row; resolves to (file, side, hunk_id,
|
|
10
|
+
// line_range) so the server can inline the enclosing hunk.
|
|
11
|
+
// - comment — inside a reviewer/LLM annotation; carries just the text.
|
|
12
|
+
// - plain — anything else (prose, the overview); carries just the text.
|
|
13
|
+
//
|
|
14
|
+
// Selections inside the console UI itself (the prompt, the drawer, the
|
|
15
|
+
// footer) resolve to null so caret moves in the textarea don't register
|
|
16
|
+
// as a pinned selection. This module is pure DOM → data; `console.ts`
|
|
17
|
+
// owns the chip, the live tracking, and the wire payload.
|
|
18
|
+
|
|
19
|
+
export interface ConsoleSelection {
|
|
20
|
+
selection_text: string;
|
|
21
|
+
selection_kind: "code" | "comment" | "plain";
|
|
22
|
+
file?: string;
|
|
23
|
+
side?: "old" | "new";
|
|
24
|
+
hunk_id?: string;
|
|
25
|
+
/** [start, end] line numbers on `side`, inclusive; collapsed to a
|
|
26
|
+
* single line when the selection stays within one row. */
|
|
27
|
+
line_range?: [number, number];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The element a (possibly text) node lives in, for `.closest()` walks. */
|
|
31
|
+
function elementOf(node: Node | null): Element | null {
|
|
32
|
+
if (!node) return null;
|
|
33
|
+
return node.nodeType === Node.ELEMENT_NODE
|
|
34
|
+
? (node as Element)
|
|
35
|
+
: node.parentElement;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Resolve a node's enclosing diff row to its (side, line) — the same
|
|
39
|
+
* shape `comments.ts` reads off `row.children[0]`. Null when the node
|
|
40
|
+
* isn't in a numbered code row. */
|
|
41
|
+
function rowLine(node: Node | null): { side: "old" | "new"; line: number } | null {
|
|
42
|
+
const row = elementOf(node)?.closest(".row");
|
|
43
|
+
if (!row) return null;
|
|
44
|
+
const cell = row.children[0] as HTMLElement | undefined;
|
|
45
|
+
if (!cell || !cell.classList.contains("cell-lineno")) return null;
|
|
46
|
+
if (cell.classList.contains("empty")) return null;
|
|
47
|
+
const side: "old" | "new" =
|
|
48
|
+
cell.classList.contains("cell-lineno-old") ? "old" : "new";
|
|
49
|
+
const line = parseInt((cell.textContent || "").trim(), 10);
|
|
50
|
+
if (isNaN(line)) return null;
|
|
51
|
+
return { side, line };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Resolve a live selection to a console hint, or null when there's
|
|
55
|
+
* nothing usable (collapsed, empty, or inside the console UI). */
|
|
56
|
+
export function resolveSelection(sel: Selection | null): ConsoleSelection | null {
|
|
57
|
+
if (!sel || sel.isCollapsed) return null;
|
|
58
|
+
const text = sel.toString().trim();
|
|
59
|
+
if (!text) return null;
|
|
60
|
+
|
|
61
|
+
const anchorEl = elementOf(sel.anchorNode);
|
|
62
|
+
if (!anchorEl) return { selection_text: text, selection_kind: "plain" };
|
|
63
|
+
|
|
64
|
+
// Ignore the console's own surfaces — a caret move in the prompt or a
|
|
65
|
+
// drag across the transcript isn't a selection of the change.
|
|
66
|
+
if (anchorEl.closest(".console-drawer, .console-input, #status-bar")) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Comment / annotation text — reviewer threads and LLM annotations.
|
|
71
|
+
if (anchorEl.closest(".comment-thread, .comment-editor-body, .row-annotation")) {
|
|
72
|
+
return { selection_text: text, selection_kind: "comment" };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Code — must sit inside a diff row of a hunk in a file.
|
|
76
|
+
const hunkEl = anchorEl.closest(".hunk");
|
|
77
|
+
const fileEl = anchorEl.closest(".file");
|
|
78
|
+
const anchor = rowLine(sel.anchorNode);
|
|
79
|
+
if (hunkEl && fileEl && anchor) {
|
|
80
|
+
const hunk_id = hunkEl.getAttribute("data-id") || undefined;
|
|
81
|
+
const pathEl = fileEl.querySelector(".file-path");
|
|
82
|
+
const file = pathEl ? (pathEl.textContent || "").trim() : "";
|
|
83
|
+
// The focus row may differ from the anchor row on a multi-line drag;
|
|
84
|
+
// keep the range on the anchor's side and span the two line numbers.
|
|
85
|
+
const focus = rowLine(sel.focusNode);
|
|
86
|
+
const lines = [anchor.line];
|
|
87
|
+
if (focus && focus.side === anchor.side) lines.push(focus.line);
|
|
88
|
+
const lo = Math.min(...lines);
|
|
89
|
+
const hi = Math.max(...lines);
|
|
90
|
+
const out: ConsoleSelection = {
|
|
91
|
+
selection_text: text,
|
|
92
|
+
selection_kind: "code",
|
|
93
|
+
side: anchor.side,
|
|
94
|
+
line_range: [lo, hi],
|
|
95
|
+
};
|
|
96
|
+
if (file) out.file = file;
|
|
97
|
+
if (hunk_id) out.hunk_id = hunk_id;
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return { selection_text: text, selection_kind: "plain" };
|
|
102
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// Typed mutators for the viewer's in-memory [[viewer-data]] tree.
|
|
2
|
+
//
|
|
3
|
+
// Before this module existed, boot.ts owned a few hundred lines of
|
|
4
|
+
// SSE-handler logic that walked DATA in place, mutated nested slots,
|
|
5
|
+
// and silently augmented HunkBlock / FoldRegion with private
|
|
6
|
+
// `_failed` / `_inflight` flags via local `... extends HunkBlock`
|
|
7
|
+
// interfaces. The renderer and folds.ts independently re-declared
|
|
8
|
+
// the same augmentations — three places, no shared contract.
|
|
9
|
+
//
|
|
10
|
+
// This module owns those mutations. boot.ts's SSE handlers shrink to
|
|
11
|
+
// "translate payload into a DataStore call, then ask the right module
|
|
12
|
+
// to repaint." The viewer-runtime fields (`_failed`, `_inflight`) are
|
|
13
|
+
// now part of HunkBlock / FoldRegion in types.d.ts; DataStore is
|
|
14
|
+
// their canonical writer.
|
|
15
|
+
//
|
|
16
|
+
// Functional API: every mutator takes the `ViewerData` reference as
|
|
17
|
+
// its first argument. boot.ts still holds the reference (it owns the
|
|
18
|
+
// `/data.json` fetch result); DataStore is stateless. That keeps the
|
|
19
|
+
// existing pattern where Comments.init / Sidebar.init / Render.init
|
|
20
|
+
// each receive the same reference and see mutations through it.
|
|
21
|
+
|
|
22
|
+
export interface FoldRegionAddress {
|
|
23
|
+
file_idx: number;
|
|
24
|
+
context: FoldContext;
|
|
25
|
+
right_start: number;
|
|
26
|
+
right_end: number;
|
|
27
|
+
left_start: number;
|
|
28
|
+
left_end: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ResolvedFoldRegion {
|
|
32
|
+
file: FileBlock;
|
|
33
|
+
/** Index into `file.hunks` of the hunk whose `fold_regions` list
|
|
34
|
+
* carries the addressed region. Regions are addressed at the file
|
|
35
|
+
* level but persisted on individual hunks (today, the first hunk
|
|
36
|
+
* of the file — see CONTEXT.md `Fold region`). */
|
|
37
|
+
hostHunkIdx: number;
|
|
38
|
+
region: FoldRegion;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type FoldSummaryResult = "applied" | "noop" | "inflight" | "not-found";
|
|
42
|
+
|
|
43
|
+
export interface OverviewApplyResult {
|
|
44
|
+
/** True iff `payload.groups` was non-empty; tells boot.ts whether
|
|
45
|
+
* to refresh the themes axis in addition to a full re-render. */
|
|
46
|
+
groupsChanged: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const DataStore = {
|
|
50
|
+
// --- Overview / per-file metadata ----------------------------------
|
|
51
|
+
|
|
52
|
+
applyOverview(data: ViewerData, payload: SseOverviewEvent): OverviewApplyResult {
|
|
53
|
+
if (payload.pr) {
|
|
54
|
+
Object.assign(data.pr || (data.pr = {} as PRBlock), payload.pr);
|
|
55
|
+
}
|
|
56
|
+
if (Array.isArray(payload.files)) {
|
|
57
|
+
for (const fp of payload.files) {
|
|
58
|
+
const f = data.files && data.files[fp.file_idx];
|
|
59
|
+
if (!f) continue;
|
|
60
|
+
if (fp.summary !== undefined) f.summary = fp.summary;
|
|
61
|
+
if (fp.language) f.language = fp.language;
|
|
62
|
+
if (fp.symbols) f.symbols = fp.symbols;
|
|
63
|
+
if (fp.status) f.status = fp.status;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const groupsChanged = Array.isArray(payload.groups);
|
|
67
|
+
if (groupsChanged) {
|
|
68
|
+
data.groups = payload.groups!;
|
|
69
|
+
}
|
|
70
|
+
return { groupsChanged };
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
// --- Per-hunk replacement ------------------------------------------
|
|
74
|
+
|
|
75
|
+
/** Splice an augmented HunkBlock into the tree. Returns the file
|
|
76
|
+
* whose hunk was replaced (so the caller can hand it to
|
|
77
|
+
* Render.renderHunkReplace), or null if the address is invalid. */
|
|
78
|
+
replaceHunk(
|
|
79
|
+
data: ViewerData, file_idx: number, hunk_idx: number, block: HunkBlock,
|
|
80
|
+
): FileBlock | null {
|
|
81
|
+
const file = data.files && data.files[file_idx];
|
|
82
|
+
if (!file || !file.hunks || !file.hunks[hunk_idx]) return null;
|
|
83
|
+
file.hunks[hunk_idx] = block;
|
|
84
|
+
return file;
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
/** Mark a hunk slot as failed: the renderer reads `_failed` to show
|
|
88
|
+
* "couldn't produce annotations" instead of the pending spinner. */
|
|
89
|
+
markHunkFailed(
|
|
90
|
+
data: ViewerData, file_idx: number, hunk_idx: number,
|
|
91
|
+
): FileBlock | null {
|
|
92
|
+
const file = data.files && data.files[file_idx];
|
|
93
|
+
if (!file || !file.hunks || !file.hunks[hunk_idx]) return null;
|
|
94
|
+
const hunk = file.hunks[hunk_idx];
|
|
95
|
+
hunk.intent = "";
|
|
96
|
+
hunk._failed = true;
|
|
97
|
+
return file;
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
// --- Fold regions --------------------------------------------------
|
|
101
|
+
|
|
102
|
+
/** Look up the fold region at `addr`, walking every hunk in the
|
|
103
|
+
* addressed file. Returns null if no matching region exists. */
|
|
104
|
+
findFoldRegion(data: ViewerData, addr: FoldRegionAddress): ResolvedFoldRegion | null {
|
|
105
|
+
const f = data.files && data.files[addr.file_idx];
|
|
106
|
+
if (!f) return null;
|
|
107
|
+
for (let hi = 0; hi < (f.hunks || []).length; hi++) {
|
|
108
|
+
const h = f.hunks[hi];
|
|
109
|
+
for (const r of h.fold_regions || []) {
|
|
110
|
+
if (_foldKeyMatches(r, addr)) {
|
|
111
|
+
return { file: f, hostHunkIdx: hi, region: r };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return null;
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
/** Apply a server-side fold summary to the matching region.
|
|
119
|
+
*
|
|
120
|
+
* Outcomes:
|
|
121
|
+
* "applied" — summary written; caller should re-render.
|
|
122
|
+
* "noop" — same summary already present; nothing to do.
|
|
123
|
+
* "inflight" — region's own local POST is racing this; caller
|
|
124
|
+
* must NOT re-render (the in-flight handler owns
|
|
125
|
+
* the DOM update, and a re-render would pop the
|
|
126
|
+
* user's just-closed fold back open).
|
|
127
|
+
* "not-found" — the address doesn't match any region. */
|
|
128
|
+
applyFoldSummary(
|
|
129
|
+
data: ViewerData, addr: FoldRegionAddress, summary: string,
|
|
130
|
+
): FoldSummaryResult {
|
|
131
|
+
const resolved = this.findFoldRegion(data, addr);
|
|
132
|
+
if (!resolved) return "not-found";
|
|
133
|
+
if (resolved.region.summary === summary) return "noop";
|
|
134
|
+
resolved.region.summary = summary;
|
|
135
|
+
if (resolved.region._inflight) return "inflight";
|
|
136
|
+
return "applied";
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
// --- Stream lifecycle ----------------------------------------------
|
|
140
|
+
|
|
141
|
+
finalisePending(data: ViewerData): void {
|
|
142
|
+
// Hunks the server never sent an event for (filtered, skipped,
|
|
143
|
+
// crashed mid-pass) now render the failure copy instead of the
|
|
144
|
+
// spinner on the next paint.
|
|
145
|
+
data.pending = false;
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
function _foldKeyMatches(r: FoldRegion, addr: FoldRegionAddress): boolean {
|
|
151
|
+
return (r.context || "right") === addr.context
|
|
152
|
+
&& (r.right_start || 0) === addr.right_start
|
|
153
|
+
&& (r.right_end || 0) === addr.right_end
|
|
154
|
+
&& (r.left_start || 0) === addr.left_start
|
|
155
|
+
&& (r.left_end || 0) === addr.left_end;
|
|
156
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Typed handle from the renderer to the fold-detector for the per-file
|
|
2
|
+
// row stream.
|
|
3
|
+
//
|
|
4
|
+
// Why this module exists. The fold detector (folds.ts) needs to walk
|
|
5
|
+
// every row in a file — across hunks, across expanded gap-context — in
|
|
6
|
+
// DOM order, with access to both the `RowBlock` records and the
|
|
7
|
+
// per-side DOM elements those rows materialised into. The renderer
|
|
8
|
+
// (render.ts) is the only place that has all three pieces at the
|
|
9
|
+
// moment of construction.
|
|
10
|
+
//
|
|
11
|
+
// The previous shape stashed three optional properties (`_scrRows`,
|
|
12
|
+
// `_scrRowElsOld`, `_scrRowElsNew`) directly on the `.diff` /
|
|
13
|
+
// `.gap-expansion` HTMLElements via three independently-declared
|
|
14
|
+
// HTMLElement augmentation interfaces. That worked, but the contract
|
|
15
|
+
// was triplicated, stringly-typed, and silent: a rename on the
|
|
16
|
+
// producing side broke the consuming side at runtime, not at compile
|
|
17
|
+
// time.
|
|
18
|
+
//
|
|
19
|
+
// This module owns the contract instead. `record` is called by the
|
|
20
|
+
// renderer for every `.diff` / `.gap-expansion` it builds; `get` is
|
|
21
|
+
// called by the fold detector for each candidate container as it walks
|
|
22
|
+
// `.file-body`. Storage is a `WeakMap` keyed by container reference,
|
|
23
|
+
// so entries vanish when a container is replaced (collapsed back to a
|
|
24
|
+
// chip, re-rendered after an SSE hunk replace, etc.).
|
|
25
|
+
|
|
26
|
+
export interface RowWithEls extends RowBlock {
|
|
27
|
+
oldEl: HTMLElement;
|
|
28
|
+
newEl: HTMLElement;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface FileRowsEntry {
|
|
32
|
+
rows: RowBlock[];
|
|
33
|
+
oldEls: HTMLElement[];
|
|
34
|
+
newEls: HTMLElement[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const _storage = new WeakMap<HTMLElement, FileRowsEntry>();
|
|
38
|
+
|
|
39
|
+
export const FileRows = {
|
|
40
|
+
/** Record the row stream for a `.diff` or `.gap-expansion` container. */
|
|
41
|
+
record(container: HTMLElement, entry: FileRowsEntry): void {
|
|
42
|
+
_storage.set(container, entry);
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
/** Look up a container's recorded rows, or undefined if none was set. */
|
|
46
|
+
get(container: HTMLElement): FileRowsEntry | undefined {
|
|
47
|
+
return _storage.get(container);
|
|
48
|
+
},
|
|
49
|
+
};
|