overleaf-review 0.2.1 → 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 +120 -12
- package/dist/cli.js +3254 -308
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -35,13 +35,52 @@ workflow and carries the review layer Git can't represent.
|
|
|
35
35
|
- 📥 **`pull`** — read comments + tracked changes (with anchors) into a Git-friendly sidecar
|
|
36
36
|
(`.overleaf/reviews.md` + `.json`), so your tools have every co-author note in context.
|
|
37
37
|
- 📤 **`push`** — turn local edits into **tracked-change suggestions**, mapping files to Overleaf
|
|
38
|
-
docs by path (one file, or every changed `.tex` at once).
|
|
38
|
+
docs by path (one file, or every changed `.tex` at once). A saved Base/Local/Live merge keeps
|
|
39
|
+
non-overlapping co-author edits, while overlapping edits and active tracked-change ranges stop
|
|
40
|
+
the push for inspection. `--direct` sends plain edits instead of suggestions.
|
|
41
|
+
- 🔄 **`fetch`** — write Overleaf's current text back down into your repo (read-only on Overleaf, so
|
|
42
|
+
it cannot disturb a single comment or tracked change) and save the synchronization base used by
|
|
43
|
+
future pushes. Existing local files are snapshotted before replacement.
|
|
44
|
+
- 📋 **`review plan` / `review submit`** — save a complete, binding push plan, inspect it, then
|
|
45
|
+
submit it only if the local file, saved base, live document version, and review ranges are still
|
|
46
|
+
unchanged.
|
|
47
|
+
- 🖼️ **`upload`** — push figures, PDFs, or new files into Overleaf.
|
|
39
48
|
- 💬 **`comment` / `reply` / `resolve` / `delete-comment` / `delete-message`** — full comment
|
|
40
49
|
control: start a thread, reply, resolve/reopen, delete a whole thread or a single message.
|
|
41
|
-
|
|
50
|
+
Identical recent comments and replies are retry-safe by default; `--force` deliberately posts
|
|
51
|
+
another copy.
|
|
52
|
+
- ✅ **`accept` / `reject`** — act on collaborators' tracked changes and verify removal of every
|
|
53
|
+
requested change id before reporting success; rejection also verifies the exact resulting text.
|
|
54
|
+
- 🧾 **Review receipts** — pushes, accept/reject actions, comments, and replies leave durable JSON
|
|
55
|
+
records under `.overleaf/receipts/` showing what was verified or left ambiguous.
|
|
42
56
|
- 🔑 **`login`** — validated auth stored outside your repo (chmod 600); `--browser` mode is
|
|
43
57
|
institutional-SSO friendly.
|
|
44
58
|
|
|
59
|
+
## ⚠️ Don't mix this with Overleaf's Git/GitHub sync
|
|
60
|
+
|
|
61
|
+
**Overleaf's Git integration writes documents by wholesale content replacement.** The review layer
|
|
62
|
+
is stored separately, anchored by character offsets — so a bulk overwrite orphans or displaces your
|
|
63
|
+
comments and tracked changes. (Overleaf's own docs advise against combining Git with track changes.)
|
|
64
|
+
This isn't something a tool can patch around; it's inherent to how the bridge writes.
|
|
65
|
+
|
|
66
|
+
`overleaf-review` writes through Overleaf's **real-time OT API** instead — incremental insert/delete
|
|
67
|
+
ops that Overleaf *transforms the review ranges against*, so comments and tracked changes survive.
|
|
68
|
+
|
|
69
|
+
**Recommended setup: unlink Overleaf's Git/GitHub sync and let `overleaf-review` be the only bridge.**
|
|
70
|
+
|
|
71
|
+
| Need | Command |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| Begin a local review session | `review start` |
|
|
74
|
+
| Overleaf text → your repo and save Base | `fetch` |
|
|
75
|
+
| Your edits → Overleaf, as suggestions | `push` |
|
|
76
|
+
| Your edits → Overleaf, directly | `push --direct` |
|
|
77
|
+
| Inspect, then submit the exact same change | `review plan --out plan.json`, then `review submit --plan plan.json` |
|
|
78
|
+
| Figures / new files → Overleaf | `upload` |
|
|
79
|
+
|
|
80
|
+
Your Git repo stays a completely normal repo — commit whatever you like, `.tex` included — and
|
|
81
|
+
nothing bidirectional exists that can clobber the review record. (Renaming/deleting files is still
|
|
82
|
+
done in the Overleaf UI.)
|
|
83
|
+
|
|
45
84
|
## 📦 Install
|
|
46
85
|
|
|
47
86
|
```bash
|
|
@@ -58,14 +97,28 @@ overleaf-review login --browser # opens your Chrome, log in normally (SSO work
|
|
|
58
97
|
# 2. Link this repo to an Overleaf project (id from the project URL)
|
|
59
98
|
overleaf-review link --project 6a4c…bec5a
|
|
60
99
|
|
|
61
|
-
# 3.
|
|
62
|
-
overleaf-review
|
|
63
|
-
|
|
64
|
-
|
|
100
|
+
# 3. Start from Overleaf's current text and review state
|
|
101
|
+
overleaf-review review start # fetch text + save Base + pull reviews
|
|
102
|
+
|
|
103
|
+
# 4. Edit locally, then inspect and submit a binding plan
|
|
104
|
+
overleaf-review review plan --out .overleaf/push-plan.json
|
|
105
|
+
overleaf-review review submit --plan .overleaf/push-plan.json
|
|
106
|
+
|
|
107
|
+
# Or use the safe one-shot form when a separate approval step is unnecessary
|
|
108
|
+
overleaf-review push --dry-run # transient preview; sends nothing
|
|
109
|
+
overleaf-review push # plan, validate, send, and verify
|
|
110
|
+
|
|
111
|
+
# 5. Work with review threads
|
|
65
112
|
overleaf-review comment --anchor "Introduction" --message "Expand this section"
|
|
66
113
|
overleaf-review resolve --thread <id> # thread ids come from `pull`
|
|
67
114
|
```
|
|
68
115
|
|
|
116
|
+
`fetch` and `review start` write Overleaf's text into the local files, so commit or otherwise
|
|
117
|
+
preserve local-only work before running them. They save `.overleaf/base.json`; edit only after that
|
|
118
|
+
base is established. Existing installations should run one of these commands once before their
|
|
119
|
+
first safe push. If an upgraded repository already has unpushed edits, copy or stash them, run
|
|
120
|
+
`fetch`, then restore the edits so the new Base remains the Overleaf version they were based on.
|
|
121
|
+
|
|
69
122
|
## 🧭 Commands
|
|
70
123
|
|
|
71
124
|
| Command | What it does |
|
|
@@ -73,9 +126,14 @@ overleaf-review resolve --thread <id> # thread ids come from `pull`
|
|
|
73
126
|
| `login [--cookie <v>] [--browser]` | Authenticate and store your session (SSO-friendly `--browser`) |
|
|
74
127
|
| `link --project <id>` | Link this repo to an Overleaf project (`.overleaf/config.json`) |
|
|
75
128
|
| `pull [--out <dir>]` | Read comments + tracked changes into a sidecar |
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
129
|
+
| `fetch [--file <f>] [--dry-run]` | Write Overleaf text locally, snapshot replaced files, and save Base (read-only on Overleaf) |
|
|
130
|
+
| `review start [--file <f>] [--out <dir>]` | Fetch text, save the synchronization base, and pull the review sidecar |
|
|
131
|
+
| `review plan --out <plan.json> [--file <f>] [--doc <name>] [--direct] [--allow-overlap] [--unsafe-no-base]` | Create a complete binding plan without changing Overleaf |
|
|
132
|
+
| `review submit --plan <plan.json> [--acknowledge-ambiguous]` | Submit that plan only if all recorded preconditions still match |
|
|
133
|
+
| `upload <path…> [--folder <name>]` | Upload figures / new files into Overleaf |
|
|
134
|
+
| `push [--file <f>] [--doc <name>] [--direct] [--dry-run] [--plan-out <path>] [--plan <path>] [--allow-overlap] [--unsafe-no-base] [--acknowledge-ambiguous]` | Safely merge and send local edits (all changed `.tex` if no `--file`) |
|
|
135
|
+
| `comment --anchor <text> --message <text> [--doc <name>] [--nth <n>] [--force]` | Add an anchored comment; recent identical retries are skipped unless forced |
|
|
136
|
+
| `reply --thread <id> --message <text> [--force]` | Reply to a thread; recent identical retries are skipped unless forced |
|
|
79
137
|
| `resolve --thread <id> [--reopen]` | Resolve (or reopen) a comment thread |
|
|
80
138
|
| `delete-comment --thread <id>` | Delete a whole comment thread |
|
|
81
139
|
| `delete-message --message-id <id> [--thread <id>]` | Delete a single message within a thread |
|
|
@@ -84,6 +142,52 @@ overleaf-review resolve --thread <id> # thread ids come from `pull`
|
|
|
84
142
|
|
|
85
143
|
Thread and change ids are listed by `pull` (in `.overleaf/reviews.md`).
|
|
86
144
|
|
|
145
|
+
### Safe pushes
|
|
146
|
+
|
|
147
|
+
A normal push compares three versions of each document:
|
|
148
|
+
|
|
149
|
+
- **Base** — the Overleaf text saved by the last `fetch` or successful push;
|
|
150
|
+
- **Local** — your current file;
|
|
151
|
+
- **Live** — the document as it exists in Overleaf when planning.
|
|
152
|
+
|
|
153
|
+
Your Base→Local intent is rebased onto Live. Non-overlapping live edits are preserved; genuinely
|
|
154
|
+
overlapping Base→Local and Base→Live edits abort instead of silently undoing a collaborator's
|
|
155
|
+
work. A proposed edit that intersects an active tracked-change range is also blocked by default and
|
|
156
|
+
the relevant change ids are listed.
|
|
157
|
+
|
|
158
|
+
Use `--allow-overlap` only after inspecting those tracked changes. `--unsafe-no-base` is a deliberate
|
|
159
|
+
legacy escape hatch that treats the current Live document as Base; it loses the protection against
|
|
160
|
+
co-author edits made since your local file was obtained. `--direct` changes how the validated ops
|
|
161
|
+
are represented in Overleaf, not the merge and conflict checks.
|
|
162
|
+
|
|
163
|
+
For a separate approval step, `review plan --out plan.json` stores the full operation list and its
|
|
164
|
+
preconditions, active tracked ranges, and any comment overlaps. `review submit --plan plan.json`
|
|
165
|
+
re-derives the plan from Base/Local/Live and aborts if preflight finds that the project, local source,
|
|
166
|
+
synchronization base, live document version/content, or active review ranges changed. Plans contain
|
|
167
|
+
manuscript fragments, so store or commit them with the same care as the source itself. `push
|
|
168
|
+
--plan-out <path>` and `push --plan <path>` expose the same workflow through the one-level command.
|
|
169
|
+
|
|
170
|
+
Overleaf can transform an update that races with a collaborator after the final preflight. The tool
|
|
171
|
+
therefore reads every result back and fails rather than claiming success when the exact planned text
|
|
172
|
+
is not present. A multi-file submission is not transactional; if a later file fails, its receipt
|
|
173
|
+
identifies every earlier file already verified on Overleaf.
|
|
174
|
+
|
|
175
|
+
Pushes, accept/reject actions, comments, and replies write audit receipts beneath
|
|
176
|
+
`.overleaf/receipts/`. Keep an ambiguous receipt: it means the request may have reached Overleaf but
|
|
177
|
+
readback could not prove the result, so inspect the live project before retrying. For comments and
|
|
178
|
+
replies, an identical recent message is treated as a retry and skipped; pass `--force` only when a
|
|
179
|
+
second identical message is intentional.
|
|
180
|
+
|
|
181
|
+
An ambiguous push quarantines its affected documents even if a newly generated plan has a different
|
|
182
|
+
timestamp or tracked-change seed. After waiting for delayed updates and manually reconciling the
|
|
183
|
+
receipt against live Overleaf, `--acknowledge-ambiguous` explicitly clears that submission-time
|
|
184
|
+
guard; it should never be used as an automatic retry flag.
|
|
185
|
+
|
|
186
|
+
Mutating commands are serialized by a working-tree-specific lock in the system temporary directory,
|
|
187
|
+
preventing two local agents from racing through the same preflight. A normal exit removes the lock.
|
|
188
|
+
If a process crashes and leaves it behind, the next command prints its exact path; inspect any
|
|
189
|
+
relevant receipt and the live Overleaf document before removing it manually.
|
|
190
|
+
|
|
87
191
|
## 🧠 How it works
|
|
88
192
|
|
|
89
193
|
overleaf.com's editor speaks an old **socket.io 0.9** protocol over a WebSocket. The client
|
|
@@ -93,8 +197,12 @@ overleaf.com's editor speaks an old **socket.io 0.9** protocol over a WebSocket.
|
|
|
93
197
|
- a **tracked change** is an insert/delete op with a `meta.tc` flag;
|
|
94
198
|
- a **comment** is a `c` op plus a REST post of the message text.
|
|
95
199
|
|
|
96
|
-
`push`
|
|
97
|
-
sequential OT ops,
|
|
200
|
+
`push` performs the Base/Local/Live merge described above, translates Live→merged text into
|
|
201
|
+
sequential OT ops, and waits for Overleaf's applied-update event. It then reads the document back
|
|
202
|
+
and verifies the final text—and, in suggestion mode, tracked-change ids—before updating the saved
|
|
203
|
+
base. Accept and reject operations verify that the requested ids disappeared; rejection also
|
|
204
|
+
verifies the exact planned text. Push, accept/reject, comment, and reply fail loudly when their
|
|
205
|
+
readback cannot prove success.
|
|
98
206
|
|
|
99
207
|
## ⚠️ Disclaimer
|
|
100
208
|
|
|
@@ -105,7 +213,7 @@ own account and projects. Use at your own risk.
|
|
|
105
213
|
|
|
106
214
|
## 🗺️ Roadmap
|
|
107
215
|
|
|
108
|
-
-
|
|
216
|
+
- File rename / delete (currently done in the Overleaf UI)
|
|
109
217
|
- Trusted-publishing CI
|
|
110
218
|
|
|
111
219
|
## 📝 Changelog
|