-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathadd-md-copy.py
More file actions
165 lines (142 loc) · 36.3 KB
/
Copy pathadd-md-copy.py
File metadata and controls
165 lines (142 loc) · 36.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/usr/bin/env python3
"""add-md-copy.py - install per-message and whole-conversation markdown/plain copy
controls into the Claude Code VS Code webview, without a launcher.
Appends a sentinel-delimited block to webview/index.js (the inject IIFE) and to
webview/index.css (its styles). Idempotent (detects the open sentinel), atomic
(temp file + verified rename, metadata preserved). `--revert` removes the block
by REVERSE TRANSFORM (not a backup restore), so it composes with the context-icon
patcher on the same file - removing md-copy never disturbs context-icon. A one-time
whole-file .bak-md-copy snapshot is kept for emergency manual restore only and is
NOT used by --revert (restoring it is not composition-safe).
python3 add-md-copy.py # auto-discover & patch all installs
python3 add-md-copy.py --revert # remove our block (reverse transform)
python3 add-md-copy.py /path/to/webview/index.js # explicit target(s)
The payload below is GENERATED from fixes/markdown-copy-export/webview-inject.{js,css}
by tools/gen-embeds; do not edit it by hand. Run `tools/gen-embeds` after changing
the source, and `tools/gen-embeds --check` verifies it is in sync (CI drift check).
"""
import base64
import glob
import os
import re
import shutil
import sys
import tempfile
OPEN = "/* cc-md-copy v1 */"
CLOSE = "/* /cc-md-copy v1 */"
BACKUP_SUFFIX = ".bak-md-copy"
# >>>CCWA-MD-COPY-EMBED>>> (generated by tools/gen-embeds; do not edit)
INJECT_JS = base64.b64decode("LyogY2MtbWQtY29weTogcGVyLW1lc3NhZ2UgYW5kIHdob2xlLWNvbnZlcnNhdGlvbiBjb3B5IChNYXJrZG93bikgZm9yIHRoZQogKiBDbGF1ZGUgQ29kZSBWUyBDb2RlIHdlYnZpZXcuIFNlbGYtY29udGFpbmVkIElJRkUgYXBwZW5kZWQgdG8gd2Vidmlldy9pbmRleC5qcy4KICogRWFjaCBjb250cm9sIGlzIGEgc2luZ2xlIGNsaXBib2FyZCBpY29uIHRoYXQgZmxpcHMgdG8gYSBjaGVja21hcmsgZm9yIH4ycyB3aGVuIGEKICogY29weSBhY3R1YWxseSBzdWNjZWVkcyAobm8gdGV4dCBsYWJlbCwgbm8gbWVudSkuIEFkZGl0aXZlIGFuZCByZWFkLW9ubHkgdy5yLnQuCiAqIGFwcCBzdGF0ZTsga2V5ZWQgb24gc3RhYmxlIENTUy1tb2R1bGUgY2xhc3MgcHJlZml4ZXMsIHNvIGl0IGZhaWxzIHNhZmUgKGNvbnRyb2xzCiAqIHNpbXBseSBkbyBub3QgYXBwZWFyKSBpZiBhIHByZWZpeCBtb3Zlcy4KICogRXhwb3NlcyBpdHMgcHVyZSBmdW5jdGlvbnMgZm9yIG5vZGUgdW5pdCB0ZXN0czsgYm9vdCgpcyBvbmx5IGluIGEgcmVhbCB3ZWJ2aWV3LiAqLwovKiBMZWFkaW5nICc7JyBzbyB0aGF0LCBhcHBlbmRlZCBhZnRlciB0aGUgYnVuZGxlLCB0aGlzIElJRkUgY2FuIG5ldmVyIGJlIHBhcnNlZCBhcwogKiBhIGNhbGwgb24gdGhlIGJ1bmRsZSdzIGZpbmFsIGV4cHJlc3Npb24gaWYgaXQgbGFja3MgYSB0cmFpbGluZyBzZW1pY29sb24gKEFTSQogKiBzYWZldHkgYWNyb3NzIGV4dGVuc2lvbiBidWlsZHMpLiAqLwo7KGZ1bmN0aW9uICgpIHsKICAidXNlIHN0cmljdCI7CgogIHZhciBDT05UUk9MX1BSRUZJWCA9ICJjYy1tZC1jb3B5IjsgLy8gZXZlcnkgaW5qZWN0ZWQgbm9kZSdzIGNsYXNzIHN0YXJ0cyB3aXRoIHRoaXMKICB2YXIgVVNFUl9CVUJCTEUgPSAnW2NsYXNzKj0idXNlck1lc3NhZ2VDb250YWluZXJfIl0nOwogIC8vIEFzc2lzdGFudCBtZXNzYWdlIHdyYXBwZXIuIFZlcmlmaWVkIG9uIDIuMS4xNzA6IHRoZSByZW5kZXIgZW1pdHMgZXhhY3RseSBvbmUKICAvLyBgZGF0YS10ZXN0aWQ9ImFzc2lzdGFudC1tZXNzYWdlImAgZGl2IHBlciBhc3Npc3RhbnQgdHVybiwgd2l0aCB0aGUgcmF0aW5nCiAgLy8gd2lkZ2V0IGFuZCBjb250ZW50IGJsb2NrcyBhcyBpdHMgY2hpbGRyZW4uIChUaGUgZWFybGllciBgW2RhdGEtbWVzc2FnZS1yYXRpbmddYAogIC8vIHdhcyBXUk9ORzogdGhhdCBhdHRyaWJ1dGUgc2l0cyBvbiB0aGUgbmVzdGVkIHJhdGluZyBjb250cm9sLCB3aGljaCBpcyBhbHNvIG9ubHkKICAvLyByZW5kZXJlZCBiZWhpbmQgYW4gZXhwZXJpbWVudCthbmFseXRpY3MgZ2F0ZS4pIFJlLXBpbm5lZCBpbiBUYXNrIDYuCiAgdmFyIEFTU0lTVEFOVF9CVUJCTEUgPSAnW2RhdGEtdGVzdGlkPSJhc3Npc3RhbnQtbWVzc2FnZSJdJzsKICB2YXIgTUVTU0FHRVNfQ09OVEFJTkVSID0gJ1tjbGFzcyo9Im1lc3NhZ2VzQ29udGFpbmVyXyJdJzsgLy8gZS5nLiAnW2NsYXNzKj0idGltZWxpbmVfIl0nOyAiIiAtPiBvYnNlcnZlIGRvY3VtZW50LmJvZHkKICAvLyBPcHRpb25hbCBuYXJyb3dpbmcgb25seS4gTVVTVCBiZSBhIHNpbmdsZSB3cmFwcGVyIGFyb3VuZCBBTEwgY29udGVudCBibG9ja3MsCiAgLy8gbm90IGEgcGVyLWJsb2NrIGNsYXNzIChhIHR1cm4gaGFzIG11bHRpcGxlIGJsb2NrcykuICIiIC0+IHVzZSB0aGUgYnViYmxlIGl0c2VsZgogIC8vIChhbHJlYWR5IGFnZ3JlZ2F0ZXMgYWxsIGJsb2Nrczsgc2FuaXRpemVDbG9uZSBpcyB0aGUgY29ycmVjdG5lc3MgZ2F0ZSkuCiAgdmFyIEFTU0lTVEFOVF9DT05URU5UID0gIiI7CiAgdmFyIEZFRURCQUNLX01TID0gMjAwMDsgLy8gaG93IGxvbmcgdGhlIGNoZWNrbWFyayBzaG93cyBhZnRlciBhIHN1Y2Nlc3NmdWwgY29weQoKICAvLyAtLS0tIEhUTUwgLT4gTWFya2Rvd24gKERPTSB3YWxrKSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgLy8gVXNlcyBvbmx5OiBub2RlVHlwZSwgdGFnTmFtZSwgY2hpbGROb2RlcywgdGV4dENvbnRlbnQsIGdldEF0dHJpYnV0ZSwgY2xhc3NOYW1lLgogIGZ1bmN0aW9uIGh0bWxUb01hcmtkb3duKHJvb3QpIHsKICAgIC8vIExvbmdlc3QgcnVuIG9mIGNvbnNlY3V0aXZlIGJhY2t0aWNrcyBpbiBzLCBzbyBhIGNvZGUgZGVsaW1pdGVyL2ZlbmNlIGNhbiBiZQogICAgLy8gY2hvc2VuIGxvbmdlciB0aGFuIGFueXRoaW5nIGluc2lkZSBpdCAoZWxzZSBgYGAgaW4gdGhlIGNvbnRlbnQgY2xvc2VzIGVhcmx5KS4KICAgIGZ1bmN0aW9uIGJhY2t0aWNrUnVuKHMpIHsKICAgICAgdmFyIG1heCA9IDAsIGN1ciA9IDA7CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcy5sZW5ndGg7IGkrKykgewogICAgICAgIGlmIChzLmNoYXJBdChpKSA9PT0gImAiKSB7IGN1cisrOyBpZiAoY3VyID4gbWF4KSBtYXggPSBjdXI7IH0gZWxzZSBjdXIgPSAwOwogICAgICB9CiAgICAgIHJldHVybiBtYXg7CiAgICB9CiAgICBmdW5jdGlvbiBmZW5jZShzLCBtaW4pIHsgdmFyIG4gPSBiYWNrdGlja1J1bihzKSArIDE7IGlmIChuIDwgbWluKSBuID0gbWluOyByZXR1cm4gbmV3IEFycmF5KG4gKyAxKS5qb2luKCJgIik7IH0KICAgIGZ1bmN0aW9uIGlubGluZShub2RlKSB7CiAgICAgIHZhciBvdXQgPSAiIjsKICAgICAgdmFyIGtpZHMgPSBub2RlLmNoaWxkTm9kZXMgfHwgW107CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2lkcy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBjID0ga2lkc1tpXTsKICAgICAgICBpZiAoYy5ub2RlVHlwZSA9PT0gMykgeyBvdXQgKz0gYy50ZXh0Q29udGVudCB8fCAiIjsgY29udGludWU7IH0KICAgICAgICBpZiAoYy5ub2RlVHlwZSAhPT0gMSkgY29udGludWU7CiAgICAgICAgdmFyIHRhZyA9IChjLnRhZ05hbWUgfHwgIiIpLnRvVXBwZXJDYXNlKCk7CiAgICAgICAgaWYgKHRhZyA9PT0gIkJSIikgb3V0ICs9ICJcbiI7CiAgICAgICAgZWxzZSBpZiAodGFnID09PSAiU1RST05HIiB8fCB0YWcgPT09ICJCIikgb3V0ICs9ICIqKiIgKyBpbmxpbmUoYykgKyAiKioiOwogICAgICAgIGVsc2UgaWYgKHRhZyA9PT0gIkVNIiB8fCB0YWcgPT09ICJJIikgb3V0ICs9ICIqIiArIGlubGluZShjKSArICIqIjsKICAgICAgICBlbHNlIGlmICh0YWcgPT09ICJERUwiIHx8IHRhZyA9PT0gIlMiKSBvdXQgKz0gIn5+IiArIGlubGluZShjKSArICJ+fiI7CiAgICAgICAgZWxzZSBpZiAodGFnID09PSAiQ09ERSIpIHsKICAgICAgICAgIHZhciBjdCA9IGMudGV4dENvbnRlbnQgfHwgIiI7CiAgICAgICAgICB2YXIgZCA9IGZlbmNlKGN0LCAxKTsKICAgICAgICAgIC8vIENvbW1vbk1hcmsgc3RyaXBzIG9uZSBsZWFkaW5nK3RyYWlsaW5nIHNwYWNlLCBzbyBwYWQgd2hlbiBhbiBlZGdlIGlzIGEKICAgICAgICAgIC8vIGJhY2t0aWNrIHRvIGtlZXAgaXQgZnJvbSBtZXJnaW5nIHdpdGggdGhlIGRlbGltaXRlci4KICAgICAgICAgIHZhciBwID0gKGN0LmNoYXJBdCgwKSA9PT0gImAiIHx8IGN0LmNoYXJBdChjdC5sZW5ndGggLSAxKSA9PT0gImAiKSA/ICIgIiA6ICIiOwogICAgICAgICAgb3V0ICs9IGQgKyBwICsgY3QgKyBwICsgZDsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAodGFnID09PSAiQSIpIHsKICAgICAgICAgIHZhciBocmVmID0gYy5nZXRBdHRyaWJ1dGUgPyBjLmdldEF0dHJpYnV0ZSgiaHJlZiIpIDogbnVsbDsKICAgICAgICAgIHZhciB0ID0gaW5saW5lKGMpOwogICAgICAgICAgb3V0ICs9IGhyZWYgPyAiWyIgKyB0ICsgIl0oIiArIGhyZWYgKyAiKSIgOiB0OwogICAgICAgIH0gZWxzZSBvdXQgKz0gaW5saW5lKGMpOyAvLyB1bmtub3duIGlubGluZSB3cmFwcGVyOiBrZWVwIHRleHQsIGRyb3AgdGFnCiAgICAgIH0KICAgICAgcmV0dXJuIG91dDsKICAgIH0KICAgIGZ1bmN0aW9uIGxhbmdPZihjb2RlRWwpIHsKICAgICAgdmFyIGNscyA9ICIiOwogICAgICBpZiAoY29kZUVsKSBjbHMgPSAoY29kZUVsLmdldEF0dHJpYnV0ZSAmJiBjb2RlRWwuZ2V0QXR0cmlidXRlKCJjbGFzcyIpKSB8fCBjb2RlRWwuY2xhc3NOYW1lIHx8ICIiOwogICAgICB2YXIgbSA9IC9sYW5ndWFnZS0oW0EtWmEtejAtOSsjLlwtXSspLy5leGVjKGNscyB8fCAiIik7CiAgICAgIHJldHVybiBtID8gbVsxXSA6ICIiOwogICAgfQogICAgZnVuY3Rpb24gZmluZENoaWxkVGFnKG5vZGUsIHRhZykgewogICAgICB2YXIga2lkcyA9IG5vZGUuY2hpbGROb2RlcyB8fCBbXTsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBraWRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgaWYgKGtpZHNbaV0ubm9kZVR5cGUgPT09IDEgJiYgKGtpZHNbaV0udGFnTmFtZSB8fCAiIikudG9VcHBlckNhc2UoKSA9PT0gdGFnKSByZXR1cm4ga2lkc1tpXTsKICAgICAgfQogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGZ1bmN0aW9uIGxpc3Qobm9kZSwgb3JkZXJlZCwgZGVwdGgpIHsKICAgICAgdmFyIG91dCA9ICIiLCBuID0gMTsKICAgICAgdmFyIGtpZHMgPSBub2RlLmNoaWxkTm9kZXMgfHwgW107CiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2lkcy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBsaSA9IGtpZHNbaV07CiAgICAgICAgaWYgKGxpLm5vZGVUeXBlICE9PSAxIHx8IChsaS50YWdOYW1lIHx8ICIiKS50b1VwcGVyQ2FzZSgpICE9PSAiTEkiKSBjb250aW51ZTsKICAgICAgICB2YXIgbWFya2VyID0gb3JkZXJlZCA/IG4rKyArICIuICIgOiAiLSAiOwogICAgICAgIHZhciBpbmRlbnQgPSBuZXcgQXJyYXkoZGVwdGggKyAxKS5qb2luKCIgICIpOwogICAgICAgIHZhciBsZWFkID0gIiIsIG5lc3RlZCA9ICIiOwogICAgICAgIHZhciBsayA9IGxpLmNoaWxkTm9kZXMgfHwgW107CiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBsay5sZW5ndGg7IGorKykgewogICAgICAgICAgdmFyIGNoID0gbGtbal07CiAgICAgICAgICB2YXIgY3QgPSBjaC5ub2RlVHlwZSA9PT0gMSA/IChjaC50YWdOYW1lIHx8ICIiKS50b1VwcGVyQ2FzZSgpIDogIiI7CiAgICAgICAgICBpZiAoY3QgPT09ICJVTCIpIG5lc3RlZCArPSBsaXN0KGNoLCBmYWxzZSwgZGVwdGggKyAxKTsKICAgICAgICAgIGVsc2UgaWYgKGN0ID09PSAiT0wiKSBuZXN0ZWQgKz0gbGlzdChjaCwgdHJ1ZSwgZGVwdGggKyAxKTsKICAgICAgICAgIGVsc2UgaWYgKGNoLm5vZGVUeXBlID09PSAzKSBsZWFkICs9IGNoLnRleHRDb250ZW50IHx8ICIiOwogICAgICAgICAgZWxzZSBsZWFkICs9IGlubGluZShjaCk7CiAgICAgICAgfQogICAgICAgIG91dCArPSBpbmRlbnQgKyBtYXJrZXIgKyBsZWFkLnRyaW0oKSArICJcbiIgKyBuZXN0ZWQ7CiAgICAgIH0KICAgICAgcmV0dXJuIG91dDsKICAgIH0KICAgIGZ1bmN0aW9uIHRhYmxlKG5vZGUpIHsKICAgICAgdmFyIHJvd3MgPSBbXTsKICAgICAgKGZ1bmN0aW9uIGNvbGxlY3QoY29udGFpbmVyKSB7CiAgICAgICAgdmFyIGtpZHMgPSBjb250YWluZXIuY2hpbGROb2RlcyB8fCBbXTsKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtpZHMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHZhciBjID0ga2lkc1tpXTsKICAgICAgICAgIGlmIChjLm5vZGVUeXBlICE9PSAxKSBjb250aW51ZTsKICAgICAgICAgIHZhciB0ID0gKGMudGFnTmFtZSB8fCAiIikudG9VcHBlckNhc2UoKTsKICAgICAgICAgIGlmICh0ID09PSAiVEhFQUQiIHx8IHQgPT09ICJUQk9EWSIgfHwgdCA9PT0gIlRGT09UIikgY29sbGVjdChjKTsKICAgICAgICAgIGVsc2UgaWYgKHQgPT09ICJUUiIpIHsKICAgICAgICAgICAgdmFyIGNlbGxzID0gW10sIGNjID0gYy5jaGlsZE5vZGVzIHx8IFtdOwogICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGNjLmxlbmd0aDsgaisrKSB7CiAgICAgICAgICAgICAgdmFyIGQgPSBjY1tqXTsKICAgICAgICAgICAgICBpZiAoZC5ub2RlVHlwZSAhPT0gMSkgY29udGludWU7CiAgICAgICAgICAgICAgdmFyIGR0ID0gKGQudGFnTmFtZSB8fCAiIikudG9VcHBlckNhc2UoKTsKICAgICAgICAgICAgICBpZiAoZHQgPT09ICJUSCIgfHwgZHQgPT09ICJURCIpIGNlbGxzLnB1c2goaW5saW5lKGQpLnRyaW0oKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcm93cy5wdXNoKGNlbGxzKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pKG5vZGUpOwogICAgICBpZiAoIXJvd3MubGVuZ3RoKSByZXR1cm4gIiI7CiAgICAgIHZhciBoZWFkID0gcm93c1swXSwgYm9keSA9IHJvd3Muc2xpY2UoMSk7CiAgICAgIHZhciBzZXAgPSBoZWFkLm1hcChmdW5jdGlvbiAoKSB7IHJldHVybiAiLS0tIjsgfSk7CiAgICAgIHZhciBvdXQgPSAifCAiICsgaGVhZC5qb2luKCIgfCAiKSArICIgfFxufCAiICsgc2VwLmpvaW4oIiB8ICIpICsgIiB8XG4iOwogICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJvZHkubGVuZ3RoOyBrKyspIG91dCArPSAifCAiICsgYm9keVtrXS5qb2luKCIgfCAiKSArICIgfFxuIjsKICAgICAgcmV0dXJuIG91dDsKICAgIH0KICAgIGZ1bmN0aW9uIGJsb2NrKG5vZGUpIHsKICAgICAgdmFyIG91dCA9ICIiOwogICAgICB2YXIga2lkcyA9IG5vZGUuY2hpbGROb2RlcyB8fCBbXTsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBraWRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIGMgPSBraWRzW2ldOwogICAgICAgIGlmIChjLm5vZGVUeXBlID09PSAzKSB7IGlmICgoYy50ZXh0Q29udGVudCB8fCAiIikudHJpbSgpKSBvdXQgKz0gYy50ZXh0Q29udGVudDsgY29udGludWU7IH0KICAgICAgICBpZiAoYy5ub2RlVHlwZSAhPT0gMSkgY29udGludWU7CiAgICAgICAgdmFyIHRhZyA9IChjLnRhZ05hbWUgfHwgIiIpLnRvVXBwZXJDYXNlKCk7CiAgICAgICAgaWYgKC9eSFsxLTZdJC8udGVzdCh0YWcpKSBvdXQgKz0gbmV3IEFycmF5KCt0YWdbMV0gKyAxKS5qb2luKCIjIikgKyAiICIgKyBpbmxpbmUoYykudHJpbSgpICsgIlxuXG4iOwogICAgICAgIGVsc2UgaWYgKHRhZyA9PT0gIlAiKSBvdXQgKz0gaW5saW5lKGMpLnRyaW0oKSArICJcblxuIjsKICAgICAgICBlbHNlIGlmICh0YWcgPT09ICJVTCIpIG91dCArPSBsaXN0KGMsIGZhbHNlLCAwKSArICJcbiI7CiAgICAgICAgZWxzZSBpZiAodGFnID09PSAiT0wiKSBvdXQgKz0gbGlzdChjLCB0cnVlLCAwKSArICJcbiI7CiAgICAgICAgZWxzZSBpZiAodGFnID09PSAiUFJFIikgewogICAgICAgICAgdmFyIGNvZGUgPSBmaW5kQ2hpbGRUYWcoYywgIkNPREUiKTsKICAgICAgICAgIHZhciBsYW5nID0gbGFuZ09mKGNvZGUgfHwgYyk7CiAgICAgICAgICB2YXIgYm9keSA9IChjb2RlIHx8IGMpLnRleHRDb250ZW50IHx8ICIiOwogICAgICAgICAgdmFyIGYgPSBmZW5jZShib2R5LCAzKTsKICAgICAgICAgIG91dCArPSBmICsgbGFuZyArICJcbiIgKyBib2R5LnJlcGxhY2UoL1xuJC8sICIiKSArICJcbiIgKyBmICsgIlxuXG4iOwogICAgICAgIH0gZWxzZSBpZiAodGFnID09PSAiQkxPQ0tRVU9URSIpIHsKICAgICAgICAgIHZhciBpbm5lciA9IGJsb2NrKGMpLnRyaW0oKS5zcGxpdCgiXG4iKS5tYXAoZnVuY3Rpb24gKGwpIHsgcmV0dXJuICI+ICIgKyBsOyB9KS5qb2luKCJcbiIpOwogICAgICAgICAgb3V0ICs9IGlubmVyICsgIlxuXG4iOwogICAgICAgIH0gZWxzZSBpZiAodGFnID09PSAiREVUQUlMUyIpIG91dCArPSBibG9jayhjKS50cmltKCkgKyAiXG5cbiI7CiAgICAgICAgZWxzZSBpZiAodGFnID09PSAiU1VNTUFSWSIpIG91dCArPSBpbmxpbmUoYykudHJpbSgpICsgIlxuXG4iOwogICAgICAgIGVsc2UgaWYgKHRhZyA9PT0gIkhSIikgb3V0ICs9ICItLS1cblxuIjsKICAgICAgICBlbHNlIGlmICh0YWcgPT09ICJUQUJMRSIpIG91dCArPSB0YWJsZShjKSArICJcbiI7CiAgICAgICAgZWxzZSBpZiAodGFnID09PSAiQlIiKSBvdXQgKz0gIlxuIjsKICAgICAgICBlbHNlIGlmICh0YWcgPT09ICJTVFJPTkciIHx8IHRhZyA9PT0gIkIiIHx8IHRhZyA9PT0gIkVNIiB8fCB0YWcgPT09ICJJIiB8fAogICAgICAgICAgICAgICAgIHRhZyA9PT0gIkEiIHx8IHRhZyA9PT0gIkNPREUiIHx8IHRhZyA9PT0gIkRFTCIgfHwgdGFnID09PSAiUyIpCiAgICAgICAgICBvdXQgKz0gaW5saW5lKGMpICsgIlxuXG4iOwogICAgICAgIGVsc2Ugb3V0ICs9IGJsb2NrKGMpOyAvLyB1bmtub3duIHdyYXBwZXI6IHJlY3Vyc2UgKGRyb3AgdGFnLCBrZWVwIGNvbnRlbnQpCiAgICAgIH0KICAgICAgcmV0dXJuIG91dDsKICAgIH0KICAgIC8vIGJsb2NrKCkgZGlzcGF0Y2hlcyBvbiBlYWNoIENISUxEJ3MgdGFnLCB0cmVhdGluZyB0aGUgcGFzc2VkIG5vZGUgYXMgYSBwbGFpbgogICAgLy8gY29udGFpbmVyLiBXcmFwIHJvb3QgaW4gYSBvbmUtb2ZmIGNvbnRhaW5lciBzbyByb290J3MgT1dOIHRhZyBpcyBkaXNwYXRjaGVkCiAgICAvLyB0b286IGNhbGxlcnMgcGFzcyBlaXRoZXIgdGhlIGJ1YmJsZSBjb250YWluZXIgKGl0cyBibG9jayBjaGlsZHJlbiByZW5kZXIpIG9yCiAgICAvLyBhIHNpbmdsZSBibG9jayBlbGVtZW50IGxpa2UgPHByZT4vPHVsPi88dGFibGU+IChub3cgaGFuZGxlZCwgbm90IGZsYXR0ZW5lZCkuCiAgICByZXR1cm4gYmxvY2soeyBjaGlsZE5vZGVzOiBbcm9vdF0gfSkucmVwbGFjZSgvXG57Myx9L2csICJcblxuIikudHJpbSgpOwogIH0KCiAgLy8gLS0tLSBwdXJlIGhlbHBlcnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIGZ1bmN0aW9uIGhhc1ByZWZpeChub2RlLCBwcmVmaXgpIHsKICAgIGlmIChub2RlLm5vZGVUeXBlICE9PSAxIHx8IHR5cGVvZiBub2RlLmNsYXNzTmFtZSAhPT0gInN0cmluZyIpIHJldHVybiBmYWxzZTsKICAgIHZhciBwYXJ0cyA9IG5vZGUuY2xhc3NOYW1lLnNwbGl0KC9ccysvKTsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIGlmIChwYXJ0c1tpXS5pbmRleE9mKHByZWZpeCkgPT09IDApIHJldHVybiB0cnVlOwogICAgcmV0dXJuIGZhbHNlOwogIH0KCiAgLy8gQ2xhc3MtcHJlZml4IGhvb2tzIGZvciBub24tY29udGVudCBjaHJvbWUgdGhhdCByZW5kZXJzICppbnNpZGUqIGFuIGFzc2lzdGFudAogIC8vIGJ1YmJsZSAodmVyaWZpZWQgb24gMi4xLjE3MDsgVGFzayA2IHJlLXBpbnMgdGhlc2UpLiBUb29sIGJsb2NrcyBhcmUgZXhjbHVkZWQKICAvLyBmcm9tIG1lc3NhZ2UgY29weTsgdGhpbmtpbmcgc3VtbWFyaWVzIGFyZSB2aXNpYmxlIGNvbnRlbnQgYW5kIG11c3QgcmVtYWluCiAgLy8gY29weWFibGUuIHVua25vd25Db250ZW50XyBpcyB0aGUgcmVuZGVyZXIncyBmYWxsYmFjayBmb3IgdW5yZWNvZ25pemVkIGJsb2NrCiAgLy8gdHlwZXMsIHNvIHN0cmlwcGluZyBpdCBtYWtlcyBhICpmdXR1cmUqIGJsb2NrIHR5cGUgZmFpbCBzYWZlIHRvIGV4Y2x1ZGVkIHJhdGhlcgogIC8vIHRoYW4gbGVha2luZyAiVW5zdXBwb3J0ZWQgY29udGVudCIgaW50byB0aGUgY29weS4gUmUtcGluIGlmIGEgcHJlZml4IG1vdmVzLgogIHZhciBDSFJPTUVfUFJFRklYRVMgPSBbInRvb2xVc2VfIiwgInRvb2xSZXN1bHRfIiwgInRvb2xSZWZlcmVuY2VfIiwgInVua25vd25Db250ZW50XyJdOwoKICAvLyBUcnVlIGZvciBhbnkgbm9kZSB0aGF0IG11c3QgbmV2ZXIgYXBwZWFyIGluIGNvcGllZCBvdXRwdXQ6IG91ciBvd24gY29udHJvbHMsCiAgLy8gdGhlIHJhdGluZyB3aWRnZXQgKGBkYXRhLW1lc3NhZ2UtcmF0aW5nYCArIGl0cyAiVGhhbmtzIGZvciB5b3VyIGZlZWRiYWNrIgogIC8vIHRleHQpLCBhbnkgYnV0dG9uIChjb3B5LWNvZGUgY2hyb21lKSwgYW5kIHRoZSBleGNsdWRlZCBjb250ZW50IGJsb2NrcyBhYm92ZS4KICBmdW5jdGlvbiBpc0Nocm9tZShub2RlKSB7CiAgICBpZiAobm9kZS5ub2RlVHlwZSAhPT0gMSkgcmV0dXJuIGZhbHNlOwogICAgaWYgKChub2RlLnRhZ05hbWUgfHwgIiIpLnRvVXBwZXJDYXNlKCkgPT09ICJCVVRUT04iKSByZXR1cm4gdHJ1ZTsKICAgIGlmIChub2RlLmdldEF0dHJpYnV0ZSAmJiBub2RlLmdldEF0dHJpYnV0ZSgiZGF0YS1tZXNzYWdlLXJhdGluZyIpICE9PSBudWxsKSByZXR1cm4gdHJ1ZTsKICAgIGlmIChoYXNQcmVmaXgobm9kZSwgQ09OVFJPTF9QUkVGSVgpKSByZXR1cm4gdHJ1ZTsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgQ0hST01FX1BSRUZJWEVTLmxlbmd0aDsgaSsrKSBpZiAoaGFzUHJlZml4KG5vZGUsIENIUk9NRV9QUkVGSVhFU1tpXSkpIHJldHVybiB0cnVlOwogICAgcmV0dXJuIGZhbHNlOwogIH0KCiAgLy8gRGVlcC1jbG9uZSBgY29udGVudE5vZGVgLCB0aGVuIHN0cmlwIGV2ZXJ5IGNocm9tZSBub2RlIHNvIGNvcGllZCBvdXRwdXQgaXMgdGhlCiAgLy8gbWVzc2FnZSdzIHRleHQgY29udGVudCBvbmx5LiBUaGlzIGlzIGEgQ09SUkVDVE5FU1MgR0FURSwgbm90IGNvc21ldGljOiB0aGUKICAvLyBkZWZhdWx0IGNvbnRlbnQgbm9kZSBpcyB0aGUgd2hvbGUgYnViYmxlIChhbGwgY29udGVudC1ibG9jayBzaWJsaW5ncywgc28gbXVsdGktCiAgLy8gYmxvY2sgYXNzaXN0YW50IHR1cm5zIGFyZSBjYXB0dXJlZCksIGFuZCB0aGlzIHN0cmlwLWxpc3QgaXMgdGhlIG9ubHkgdGhpbmcKICAvLyBrZWVwaW5nIHRoZSByYXRpbmcgd2lkZ2V0IGFuZCBleGNsdWRlZCB0b29sL2ZhbGxiYWNrIGJsb2NrcyBvdXQgb2YgdGhlIGNvcHkuCiAgZnVuY3Rpb24gc2FuaXRpemVDbG9uZShjb250ZW50Tm9kZSkgewogICAgdmFyIGNsb25lID0gY29udGVudE5vZGUuY2xvbmVOb2RlKHRydWUpOwogICAgKGZ1bmN0aW9uIHN0cmlwKG5vZGUpIHsKICAgICAgdmFyIGtpZHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChub2RlLmNoaWxkTm9kZXMgfHwgW10pOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtpZHMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgYyA9IGtpZHNbaV07CiAgICAgICAgaWYgKGMubm9kZVR5cGUgPT09IDEgJiYgaXNDaHJvbWUoYykpIHsgbm9kZS5yZW1vdmVDaGlsZChjKTsgY29udGludWU7IH0KICAgICAgICBpZiAoYy5ub2RlVHlwZSA9PT0gMSkgc3RyaXAoYyk7CiAgICAgIH0KICAgIH0pKGNsb25lKTsKICAgIHJldHVybiBjbG9uZTsKICB9CgogIGZ1bmN0aW9uIGhhc0NvcHlhYmxlQ29udGVudChjb250ZW50Tm9kZSwgcm9sZSkgewogICAgZnVuY3Rpb24gd2Fsayhub2RlKSB7CiAgICAgIGlmICghbm9kZSkgcmV0dXJuIGZhbHNlOwogICAgICBpZiAobm9kZS5ub2RlVHlwZSA9PT0gMykgcmV0dXJuICEhKG5vZGUudGV4dENvbnRlbnQgfHwgIiIpLnRyaW0oKTsKICAgICAgaWYgKG5vZGUubm9kZVR5cGUgIT09IDEpIHJldHVybiBmYWxzZTsKICAgICAgaWYgKGlzQ2hyb21lKG5vZGUpKSByZXR1cm4gZmFsc2U7CiAgICAgIHZhciBraWRzID0gbm9kZS5jaGlsZE5vZGVzIHx8IFtdOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtpZHMubGVuZ3RoOyBpKyspIGlmICh3YWxrKGtpZHNbaV0pKSByZXR1cm4gdHJ1ZTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgcmV0dXJuIHdhbGsoY29udGVudE5vZGUpOwogIH0KCiAgZnVuY3Rpb24gY2xhc3NpZnlCdWJibGUobm9kZSkgewogICAgaWYgKG5vZGUubm9kZVR5cGUgIT09IDEpIHJldHVybiBudWxsOwogICAgaWYgKGhhc1ByZWZpeChub2RlLCAidXNlck1lc3NhZ2VDb250YWluZXJfIikpIHJldHVybiAidXNlciI7CiAgICBpZiAobm9kZS5nZXRBdHRyaWJ1dGUgJiYgbm9kZS5nZXRBdHRyaWJ1dGUoImRhdGEtdGVzdGlkIikgPT09ICJhc3Npc3RhbnQtbWVzc2FnZSIpIHJldHVybiAiYXNzaXN0YW50IjsKICAgIHJldHVybiBudWxsOwogIH0KCiAgLy8gQnVpbGQgdGhlIHdob2xlLWNvbnZlcnNhdGlvbiBtYXJrZG93biBmcm9tIGFuIG9yZGVyZWQgbGlzdCBvZiBidWJibGVzLgogIC8vIGBjb250ZW50T2YoYnViYmxlKWAgcmVzb2x2ZXMgdGhlIGNvbnRlbnQgbm9kZSAoZGVmYXVsdDogdGhlIGJ1YmJsZSBpdHNlbGYsIHNvCiAgLy8gZXZlcnkgY29udGVudCBibG9jayBpcyBpbmNsdWRlZDsgc2FuaXRpemVDbG9uZSBkcm9wcyBjaHJvbWUpOyBhIGRlZmF1bHQgaXMKICAvLyBwcm92aWRlZCBmb3IgdGVzdHMuCiAgZnVuY3Rpb24gY29udmVyc2F0aW9uVG9NYXJrZG93bihidWJibGVzLCBjb250ZW50T2YpIHsKICAgIGNvbnRlbnRPZiA9IGNvbnRlbnRPZiB8fCBmdW5jdGlvbiAoYikgeyByZXR1cm4gYjsgfTsKICAgIHZhciBwYXJ0cyA9IFtdOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBidWJibGVzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciByb2xlID0gY2xhc3NpZnlCdWJibGUoYnViYmxlc1tpXSk7CiAgICAgIGlmICghcm9sZSkgY29udGludWU7CiAgICAgIHZhciBjbGVhbiA9IHNhbml0aXplQ2xvbmUoY29udGVudE9mKGJ1YmJsZXNbaV0pKTsKICAgICAgdmFyIGJvZHkgPSByb2xlID09PSAiYXNzaXN0YW50IiA/IGh0bWxUb01hcmtkb3duKGNsZWFuKSA6IChjbGVhbi50ZXh0Q29udGVudCB8fCAiIikudHJpbSgpOwogICAgICBpZiAoIWJvZHkpIGNvbnRpbnVlOwogICAgICBwYXJ0cy5wdXNoKChyb2xlID09PSAidXNlciIgPyAiIyMgVXNlciIgOiAiIyMgQXNzaXN0YW50IikgKyAiXG5cbiIgKyBib2R5KTsKICAgIH0KICAgIHJldHVybiBwYXJ0cy5qb2luKCJcblxuIikgKyAocGFydHMubGVuZ3RoID8gIlxuIiA6ICIiKTsKICB9CgogIC8vIC0tLS0gZXhwb3J0cyAobm9kZSB0ZXN0cykgLyBib290IChyZWFsIHdlYnZpZXcpIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAidW5kZWZpbmVkIikgewogICAgYm9vdCgpOwogIH0gZWxzZSBpZiAodHlwZW9mIG1vZHVsZSAhPT0gInVuZGVmaW5lZCIgJiYgbW9kdWxlLmV4cG9ydHMpIHsKICAgIG1vZHVsZS5leHBvcnRzID0geyBodG1sVG9NYXJrZG93bjogaHRtbFRvTWFya2Rvd24sIHNhbml0aXplQ2xvbmU6IHNhbml0aXplQ2xvbmUsCiAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NpZnlCdWJibGU6IGNsYXNzaWZ5QnViYmxlLCBjb252ZXJzYXRpb25Ub01hcmtkb3duOiBjb252ZXJzYXRpb25Ub01hcmtkb3duLAogICAgICAgICAgICAgICAgICAgICAgIGhhc0NvcHlhYmxlQ29udGVudDogaGFzQ29weWFibGVDb250ZW50LCBjb3B5VGV4dDogY29weVRleHQgfTsKICB9CgogIC8vIC0tLS0gbGl2ZS13ZWJ2aWV3IHdpcmluZyAocnVucyBvbmx5IHdoZW4gYSBkb2N1bWVudCBleGlzdHMpIC0tLS0tLS0tLS0tLS0tLS0KICBmdW5jdGlvbiBxcyhub2RlLCBzZWwpIHsgdHJ5IHsgcmV0dXJuIHNlbCAmJiBub2RlLnF1ZXJ5U2VsZWN0b3IgPyBub2RlLnF1ZXJ5U2VsZWN0b3Ioc2VsKSA6IG51bGw7IH0gY2F0Y2ggKF8pIHsgcmV0dXJuIG51bGw7IH0gfQogIGZ1bmN0aW9uIHFzYShzZWwpIHsgdHJ5IHsgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsKSk7IH0gY2F0Y2ggKF8pIHsgcmV0dXJuIFtdOyB9IH0KCiAgLy8gVGhlIGNvbnRlbnQgbm9kZSB0byBjb252ZXJ0L2NvcHk6IHRoZSBvcHRpb25hbCBBU1NJU1RBTlRfQ09OVEVOVCB3cmFwcGVyIGlmCiAgLy8gcGlubmVkIGFuZCBwcmVzZW50LCBlbHNlIHRoZSBidWJibGUgaXRzZWxmLiBUaGUgYnViYmxlIGFscmVhZHkgY29udGFpbnMgZXZlcnkKICAvLyBjb250ZW50LWJsb2NrIHNpYmxpbmcgb2YgYSBtdWx0aS1ibG9jayB0dXJuLCBhbmQgc2FuaXRpemVDbG9uZSBzdHJpcHMgdGhlCiAgLy8gY2hyb21lIChyYXRpbmcgd2lkZ2V0LCB0b29sL3Vua25vd24gYmxvY2tzLCBidXR0b25zLCBvdXIgY29udHJvbHMpCiAgLy8gZWl0aGVyIHdheSAtLSBzbyB0aGlzIGlzIGEgbmFycm93aW5nLCBuZXZlciB0aGUgdGhpbmcgdGhhdCBndWFyYW50ZWVzCiAgLy8gY29ycmVjdG5lc3MuCiAgZnVuY3Rpb24gY29udGVudE5vZGVPZihidWJibGUsIHJvbGUpIHsKICAgIGlmIChyb2xlID09PSAiYXNzaXN0YW50IiAmJiBBU1NJU1RBTlRfQ09OVEVOVCkgewogICAgICB2YXIgbiA9IHFzKGJ1YmJsZSwgQVNTSVNUQU5UX0NPTlRFTlQpOwogICAgICBpZiAobikgcmV0dXJuIG47CiAgICB9CiAgICByZXR1cm4gYnViYmxlOwogIH0KCiAgLy8gQ29weSBgc2AgdmlhIGEgc3luY2hyb25vdXMgZXhlY0NvbW1hbmQoImNvcHkiKSBvbiBhbiBvZmYtc2NyZWVuIHRleHRhcmVhLCBhbmQKICAvLyByZXBvcnQgd2hldGhlciBpdCBhY3R1YWxseSBoYXBwZW5lZC4gRG9uZSBmaXJzdCAoYW5kIHN5bmNocm9ub3VzbHkpIGJlY2F1c2UgaXQKICAvLyBydW5zIGluc2lkZSB0aGUgY2xpY2sgZ2VzdHVyZSBhbmQgd29ya3Mgd2hldGhlciBvciBub3QgdGhlIHBhZ2UgaXMgYSBzZWN1cmUKICAvLyBjb250ZXh0IC0tIHNvIGl0IGNvdmVycyByZW1vdGUgLyBjb2RlLXNlcnZlciwgd2hlcmUgdGhlIGFzeW5jIENsaXBib2FyZCBBUEkgaXMKICAvLyBzaW1wbHkgYWJzZW50LiBSZXN0b3JlcyB0aGUgcHJpb3Igc2VsZWN0aW9uL2ZvY3VzIHNvIGl0IGlzIGludmlzaWJsZS4KICBmdW5jdGlvbiBleGVjQ29weShzKSB7CiAgICB0cnkgewogICAgICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAidW5kZWZpbmVkIiB8fCAhZG9jdW1lbnQuY3JlYXRlRWxlbWVudCkgcmV0dXJuIGZhbHNlOwogICAgICB2YXIgcHJldiA9IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgfHwgbnVsbDsKICAgICAgdmFyIHNlbCA9IGRvY3VtZW50LmdldFNlbGVjdGlvbiA/IGRvY3VtZW50LmdldFNlbGVjdGlvbigpIDogbnVsbDsKICAgICAgdmFyIHNhdmVkID0gKHNlbCAmJiBzZWwucmFuZ2VDb3VudCkgPyBzZWwuZ2V0UmFuZ2VBdCgwKSA6IG51bGw7CiAgICAgIHZhciB0YSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInRleHRhcmVhIik7CiAgICAgIHRhLnZhbHVlID0gczsKICAgICAgdGEuc2V0QXR0cmlidXRlKCJyZWFkb25seSIsICIiKTsKICAgICAgdGEuc3R5bGUucG9zaXRpb24gPSAiZml4ZWQiOwogICAgICB0YS5zdHlsZS50b3AgPSAiLTEwMDBweCI7CiAgICAgIHRhLnN0eWxlLmxlZnQgPSAiMCI7CiAgICAgIHRhLnN0eWxlLm9wYWNpdHkgPSAiMCI7CiAgICAgIChkb2N1bWVudC5ib2R5IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkuYXBwZW5kQ2hpbGQodGEpOwogICAgICB0YS5mb2N1cygpOwogICAgICB0YS5zZWxlY3QoKTsKICAgICAgdmFyIG9rID0gZmFsc2U7CiAgICAgIHRyeSB7IG9rID0gZG9jdW1lbnQuZXhlY0NvbW1hbmQoImNvcHkiKTsgfSBjYXRjaCAoXykgeyBvayA9IGZhbHNlOyB9CiAgICAgIGlmICh0YS5wYXJlbnROb2RlKSB0YS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRhKTsKICAgICAgaWYgKHNhdmVkICYmIHNlbCkgeyB0cnkgeyBzZWwucmVtb3ZlQWxsUmFuZ2VzKCk7IHNlbC5hZGRSYW5nZShzYXZlZCk7IH0gY2F0Y2ggKF8pIHt9IH0KICAgICAgaWYgKHByZXYgJiYgcHJldi5mb2N1cykgeyB0cnkgeyBwcmV2LmZvY3VzKCk7IH0gY2F0Y2ggKF8pIHt9IH0KICAgICAgcmV0dXJuICEhb2s7CiAgICB9IGNhdGNoIChfKSB7IHJldHVybiBmYWxzZTsgfQogIH0KCiAgLy8gQ29weSBgdGV4dGAgYW5kIHJlc29sdmUgdG8gd2hldGhlciB0aGUgY29weSBBQ1RVQUxMWSBoYXBwZW5lZCwgc28gY2FsbGVycyBvbmx5CiAgLy8gc2hvdyBzdWNjZXNzIG9uIGEgcmVhbCBjb3B5IC0tIG5ldmVyIGEgZmFsc2UgImNvcGllZCIgKHRoZSBvcmlnaW5hbCBidWc6CiAgLy8gbmF2aWdhdG9yLmNsaXBib2FyZCB3YXMgdW5kZWZpbmVkIGluIHRoZSB3ZWJ2aWV3LCB0aGUgY29kZSBmZWxsIHRocm91Z2ggdG8KICAvLyBQcm9taXNlLnJlc29sdmUoKSwgYW5kIHRoZSBVSSBjbGFpbWVkIHN1Y2Nlc3Mgd2hpbGUgbm90aGluZyB3YXMgd3JpdHRlbikuIEVtcHR5CiAgLy8gdGV4dCBpcyBhIG5vbi1jb3B5IC0+IGZhbHNlLiBleGVjQ29tbWFuZCBmaXJzdCAoZ2VzdHVyZS1zYWZlLCBzZWN1cmUtY29udGV4dC0KICAvLyBpbmRlcGVuZGVudCk7IHRoZSBhc3luYyBDbGlwYm9hcmQgQVBJIGlzIHRoZSBmYWxsYmFjay4gTmV2ZXIgdGhyb3dzLgogIGZ1bmN0aW9uIGNvcHlUZXh0KHRleHQpIHsKICAgIHZhciBzID0gKHRleHQgPT0gbnVsbCkgPyAiIiA6IFN0cmluZyh0ZXh0KTsKICAgIGlmICghcykgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7CiAgICBpZiAoZXhlY0NvcHkocykpIHJldHVybiBQcm9taXNlLnJlc29sdmUodHJ1ZSk7CiAgICB0cnkgewogICAgICBpZiAodHlwZW9mIG5hdmlnYXRvciAhPT0gInVuZGVmaW5lZCIgJiYgbmF2aWdhdG9yLmNsaXBib2FyZCAmJiBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dCkgewogICAgICAgIHJldHVybiBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dChzKS50aGVuKAogICAgICAgICAgZnVuY3Rpb24gKCkgeyByZXR1cm4gdHJ1ZTsgfSwKICAgICAgICAgIGZ1bmN0aW9uICgpIHsgcmV0dXJuIGZhbHNlOyB9CiAgICAgICAgKTsKICAgICAgfQogICAgfSBjYXRjaCAoXykge30KICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZmFsc2UpOwogIH0KCiAgZnVuY3Rpb24gYnViYmxlTWFya2Rvd24oYnViYmxlLCByb2xlKSB7CiAgICB2YXIgY2xlYW4gPSBzYW5pdGl6ZUNsb25lKGNvbnRlbnROb2RlT2YoYnViYmxlLCByb2xlKSk7CiAgICByZXR1cm4gcm9sZSA9PT0gImFzc2lzdGFudCIgPyBodG1sVG9NYXJrZG93bihjbGVhbikgOiAoY2xlYW4udGV4dENvbnRlbnQgfHwgIiIpLnRyaW0oKTsKICB9CgogIC8vIElubGluZSBTVkcgaWNvbnMgKGN1cnJlbnRDb2xvciwgfjE0cHgpLiBTZXQgdmlhIGlubmVySFRNTCBvbiBvdXIgb3duIGJ1dHRvbnMKICAvLyBvbmx5OyB0aGUgbWFya3VwIG5ldmVyIHJlYWNoZXMgY29waWVkIGNvbnRlbnQgKHNhbml0aXplQ2xvbmUgZHJvcHMgb3VyIG5vZGVzKS4KICB2YXIgSUNPTl9DT1BZID0gJzxzdmcgd2lkdGg9IjE0IiBoZWlnaHQ9IjE0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgYXJpYS1oaWRkZW49InRydWUiPjxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMyIgaGVpZ2h0PSIxMyIgcng9IjIiIHJ5PSIyIj48L3JlY3Q+PHBhdGggZD0iTTUgMTVINGEyIDIgMCAwIDEtMi0yVjRhMiAyIDAgMCAxIDItMmg5YTIgMiAwIDAgMSAyIDJ2MSI+PC9wYXRoPjwvc3ZnPic7CiAgdmFyIElDT05fQ0hFQ0sgPSAnPHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMi41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGFyaWEtaGlkZGVuPSJ0cnVlIj48cG9seWxpbmUgcG9pbnRzPSIyMCA2IDkgMTcgNCAxMiI+PC9wb2x5bGluZT48L3N2Zz4nOwoKICAvLyBGbGlwIHRoZSBidXR0b24gdG8gYSBjaGVja21hcmsgZm9yIEZFRURCQUNLX01TLCB0aGVuIHJlc3RvcmUuIElkZW1wb3RlbnQgYWNyb3NzCiAgLy8gcmFwaWQgY2xpY2tzIChhbnkgcGVuZGluZyByZXN0b3JlIGlzIGNsZWFyZWQgZmlyc3QpLgogIGZ1bmN0aW9uIHNob3dDb3BpZWQoYnRuKSB7CiAgICB0cnkgewogICAgICBpZiAoYnRuLl9fY2NUaW1lcikgY2xlYXJUaW1lb3V0KGJ0bi5fX2NjVGltZXIpOwogICAgICBidG4uY2xhc3NMaXN0LmFkZChDT05UUk9MX1BSRUZJWCArICItb2siKTsKICAgICAgYnRuLmlubmVySFRNTCA9IElDT05fQ0hFQ0s7CiAgICAgIGJ0bi5fX2NjVGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsKICAgICAgICB0cnkgeyBidG4uY2xhc3NMaXN0LnJlbW92ZShDT05UUk9MX1BSRUZJWCArICItb2siKTsgYnRuLmlubmVySFRNTCA9IElDT05fQ09QWTsgfSBjYXRjaCAoXykge30KICAgICAgICBidG4uX19jY1RpbWVyID0gbnVsbDsKICAgICAgfSwgRkVFREJBQ0tfTVMpOwogICAgfSBjYXRjaCAoXykge30KICB9CgogIC8vIEJ1aWxkIGEgc2luZ2xlIGNvbnRyb2w6IG9uZSBjbGlwYm9hcmQtaWNvbiBidXR0b24uIGBvbkNvcHkoKWAgaXMgaW52b2tlZAogIC8vIHN5bmNocm9ub3VzbHkgb24gY2xpY2sgKHNvIHRoZSBjb3B5IHN0YXlzIGluc2lkZSB0aGUgdXNlciBnZXN0dXJlKSBhbmQgbXVzdAogIC8vIHJldHVybiBhIFByb21pc2U8Ym9vbGVhbj47IHRoZSBjaGVja21hcmsgc2hvd3Mgb25seSB3aGVuIGl0IHJlc29sdmVzIHRydWUuIEFsbAogIC8vIG5vZGVzIGNhcnJ5IHRoZSBDT05UUk9MX1BSRUZJWCBjbGFzcyBzbyBzYW5pdGl6ZUNsb25lIHN0cmlwcyB0aGVtIGZyb20gY29waWVzLgogIGZ1bmN0aW9uIGJ1aWxkQ29udHJvbChvbkNvcHksIHRpdGxlKSB7CiAgICB2YXIgd3JhcCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNwYW4iKTsKICAgIHdyYXAuY2xhc3NOYW1lID0gQ09OVFJPTF9QUkVGSVg7CiAgICB2YXIgYnRuID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYnV0dG9uIik7CiAgICBidG4udHlwZSA9ICJidXR0b24iOwogICAgYnRuLmNsYXNzTmFtZSA9IENPTlRST0xfUFJFRklYICsgIi1idG4iOwogICAgYnRuLnRpdGxlID0gdGl0bGUgfHwgIkNvcHkgYXMgTWFya2Rvd24iOwogICAgYnRuLnNldEF0dHJpYnV0ZSgiYXJpYS1sYWJlbCIsIGJ0bi50aXRsZSk7CiAgICBidG4uaW5uZXJIVE1MID0gSUNPTl9DT1BZOwogICAgdmFyIGJ1c3kgPSBmYWxzZTsKICAgIGJ0bi5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsIGZ1bmN0aW9uIChlKSB7CiAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7CiAgICAgIGlmIChidXN5KSByZXR1cm47CiAgICAgIGJ1c3kgPSB0cnVlOwogICAgICB2YXIgcDsKICAgICAgdHJ5IHsgcCA9IG9uQ29weSgpOyB9IGNhdGNoIChfKSB7IHAgPSBmYWxzZTsgfQogICAgICBQcm9taXNlLnJlc29sdmUocCkudGhlbigKICAgICAgICBmdW5jdGlvbiAob2spIHsgYnVzeSA9IGZhbHNlOyBpZiAob2spIHNob3dDb3BpZWQoYnRuKTsgfSwKICAgICAgICBmdW5jdGlvbiAoKSB7IGJ1c3kgPSBmYWxzZTsgfQogICAgICApOwogICAgfSk7CiAgICB3cmFwLmFwcGVuZENoaWxkKGJ0bik7CiAgICByZXR1cm4gd3JhcDsKICB9CgogIGZ1bmN0aW9uIGRlY29yYXRlKGJ1YmJsZSkgewogICAgdHJ5IHsKICAgICAgdmFyIHJvbGUgPSBjbGFzc2lmeUJ1YmJsZShidWJibGUpOwogICAgICBpZiAoIXJvbGUpIHJldHVybjsKICAgICAgLy8gSWRlbXBvdGVudDoga2VlcCBleGFjdGx5IG9uZSBjb250cm9sLiBBIFJlYWN0IHJlLXJlbmRlciBvZiB0aGUgYnViYmxlIGNhbgogICAgICAvLyBsZWF2ZSBhIHN0YWxlIGNvbnRyb2wgYmVoaW5kIG9yIHRyYW5zaWVudGx5IGRlZmVhdCBhbiAiYWxyZWFkeSBkZWNvcmF0ZWQiCiAgICAgIC8vIGd1YXJkLCB3aGljaCBpcyB3aGF0IHByb2R1Y2VkIGR1cGxpY2F0ZSByb3dzIG9mIGJ1dHRvbnM7IHBydW5lIGFueSBleHRyYXMKICAgICAgLy8gZXZlcnkgc3dlZXAgYW5kIG9ubHkgYWRkIG9uZSB3aGVuIG5vbmUgcmVtYWluLgogICAgICB2YXIgZXhpc3RpbmcgPSBidWJibGUucXVlcnlTZWxlY3RvckFsbCA/IGJ1YmJsZS5xdWVyeVNlbGVjdG9yQWxsKCIuIiArIENPTlRST0xfUFJFRklYKSA6IG51bGw7CiAgICAgIGlmICghaGFzQ29weWFibGVDb250ZW50KGNvbnRlbnROb2RlT2YoYnViYmxlLCByb2xlKSwgcm9sZSkpIHsKICAgICAgICBpZiAoZXhpc3RpbmcgJiYgZXhpc3RpbmcubGVuZ3RoKSB7CiAgICAgICAgICBmb3IgKHZhciBqID0gZXhpc3RpbmcubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHsKICAgICAgICAgICAgaWYgKGV4aXN0aW5nW2pdICYmIGV4aXN0aW5nW2pdLnBhcmVudE5vZGUpIGV4aXN0aW5nW2pdLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZXhpc3Rpbmdbal0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKGV4aXN0aW5nICYmIGV4aXN0aW5nLmxlbmd0aCkgewogICAgICAgIGZvciAodmFyIGkgPSBleGlzdGluZy5sZW5ndGggLSAxOyBpID49IDE7IGktLSkgewogICAgICAgICAgaWYgKGV4aXN0aW5nW2ldICYmIGV4aXN0aW5nW2ldLnBhcmVudE5vZGUpIGV4aXN0aW5nW2ldLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZXhpc3RpbmdbaV0pOwogICAgICAgIH0KICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdmFyIGNvbnRyb2wgPSBidWlsZENvbnRyb2woZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBjb3B5VGV4dChidWJibGVNYXJrZG93bihidWJibGUsIHJvbGUpKTsKICAgICAgfSwgIkNvcHkgYXMgTWFya2Rvd24iKTsKICAgICAgYnViYmxlLmFwcGVuZENoaWxkKGNvbnRyb2wpOwogICAgfSBjYXRjaCAoXykge30KICB9CgogIGZ1bmN0aW9uIGNvcHlDb252ZXJzYXRpb24oKSB7CiAgICB2YXIgYnViYmxlcyA9IHFzYShVU0VSX0JVQkJMRSArICIsIiArIEFTU0lTVEFOVF9CVUJCTEUpOwogICAgcmV0dXJuIGNvcHlUZXh0KGNvbnZlcnNhdGlvblRvTWFya2Rvd24oYnViYmxlcywgZnVuY3Rpb24gKGIpIHsKICAgICAgcmV0dXJuIGNvbnRlbnROb2RlT2YoYiwgY2xhc3NpZnlCdWJibGUoYikpOwogICAgfSkpOwogIH0KCiAgLy8gQSBzaW5nbGUgZmxvYXRpbmcgIkNvcHkgY29udmVyc2F0aW9uIiBpY29uLCBwcmVzZW50IG9ubHkgd2hpbGUgYSBjb252ZXJzYXRpb24KICAvLyBpcyBvcGVuIChzbyBpdCBuZXZlciBjbHV0dGVycyB0aGUgaGlzdG9yeS1saXN0IHZpZXcpLiBQaW5uZWQgdG9wLXJpZ2h0IGJ5IENTUywKICAvLyBjbGVhciBvZiB0aGUgY2hhdCBpbnB1dCBhdCB0aGUgYm90dG9tOyB0aGUgbW9zdC1yZWNlbnQtcHJvbXB0IHN0aWNreSBoZWFkZXIKICAvLyBzaXRzIHRvIGl0cyBsZWZ0LgogIGZ1bmN0aW9uIGluc3RhbGxDb252ZXJzYXRpb25Db250cm9sKCkgewogICAgdHJ5IHsKICAgICAgdmFyIGV4aXN0aW5nID0gcXMoZG9jdW1lbnQsICIuIiArIENPTlRST0xfUFJFRklYICsgIi1jb252ZXJzYXRpb24iKTsKICAgICAgdmFyIGhhc01lc3NhZ2VzID0gcXNhKFVTRVJfQlVCQkxFICsgIiwiICsgQVNTSVNUQU5UX0JVQkJMRSkubGVuZ3RoID4gMDsKICAgICAgaWYgKCFoYXNNZXNzYWdlcykgewogICAgICAgIGlmIChleGlzdGluZyAmJiBleGlzdGluZy5wYXJlbnROb2RlKSBleGlzdGluZy5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGV4aXN0aW5nKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKGV4aXN0aW5nKSByZXR1cm47CiAgICAgIHZhciBiYXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYiKTsKICAgICAgYmFyLmNsYXNzTmFtZSA9IENPTlRST0xfUFJFRklYICsgIi1jb252ZXJzYXRpb24iOwogICAgICBiYXIuYXBwZW5kQ2hpbGQoYnVpbGRDb250cm9sKGNvcHlDb252ZXJzYXRpb24sICJDb3B5IGNvbnZlcnNhdGlvbiIpKTsKICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChiYXIpOwogICAgfSBjYXRjaCAoXykge30KICB9CgogIGZ1bmN0aW9uIHN3ZWVwKCkgewogICAgdmFyIGIgPSBxc2EoVVNFUl9CVUJCTEUgKyAiLCIgKyBBU1NJU1RBTlRfQlVCQkxFKTsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYi5sZW5ndGg7IGkrKykgZGVjb3JhdGUoYltpXSk7CiAgICBpbnN0YWxsQ29udmVyc2F0aW9uQ29udHJvbCgpOwogIH0KCiAgZnVuY3Rpb24gYm9vdCgpIHsKICAgIHRyeSB7CiAgICAgIHZhciB0YXJnZXQgPSAoTUVTU0FHRVNfQ09OVEFJTkVSICYmIHFzKGRvY3VtZW50LCBNRVNTQUdFU19DT05UQUlORVIpKSB8fCBkb2N1bWVudC5ib2R5OwogICAgICBzd2VlcCgpOwogICAgICBpZiAodHlwZW9mIE11dGF0aW9uT2JzZXJ2ZXIgPT09ICJ1bmRlZmluZWQiKSByZXR1cm47CiAgICAgIHZhciBvYnMgPSBuZXcgTXV0YXRpb25PYnNlcnZlcihmdW5jdGlvbiAoKSB7IHN3ZWVwKCk7IH0pOwogICAgICBvYnMub2JzZXJ2ZSh0YXJnZXQsIHsgY2hpbGRMaXN0OiB0cnVlLCBzdWJ0cmVlOiB0cnVlIH0pOwogICAgfSBjYXRjaCAoXykge30KICB9Cn0pKCk7Cg==").decode("utf-8")
INJECT_CSS = base64.b64decode("LmNjLW1kLWNvcHkgewogIGRpc3BsYXk6IGlubGluZS1mbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAgdmVydGljYWwtYWxpZ246IG1pZGRsZTsKICBtYXJnaW4tbGVmdDogNnB4Owp9Ci5jYy1tZC1jb3B5LWJ0biB7CiAgZGlzcGxheTogaW5saW5lLWZsZXg7CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsKICBwYWRkaW5nOiAycHg7CiAgY29sb3I6IHZhcigtLXZzY29kZS1mb3JlZ3JvdW5kKTsKICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDsKICBib3JkZXI6IG5vbmU7CiAgYm9yZGVyLXJhZGl1czogNHB4OwogIGN1cnNvcjogcG9pbnRlcjsKICBvcGFjaXR5OiAwLjY7Cn0KLmNjLW1kLWNvcHktYnRuIHN2ZyB7CiAgZGlzcGxheTogYmxvY2s7CiAgd2lkdGg6IDE0cHg7CiAgaGVpZ2h0OiAxNHB4Owp9Ci5jYy1tZC1jb3B5LWJ0bjpob3ZlciB7CiAgb3BhY2l0eTogMTsKICBiYWNrZ3JvdW5kOiB2YXIoLS12c2NvZGUtdG9vbGJhci1ob3ZlckJhY2tncm91bmQsIHJnYmEoMTI4LCAxMjgsIDEyOCwgMC4xNSkpOwp9Ci8qIFN1Y2Nlc3Mgc3RhdGU6IHRoZSBpY29uIGlzIGEgZ3JlZW4gY2hlY2ttYXJrIGZvciBhIG1vbWVudCBhZnRlciBhIHJlYWwgY29weS4gKi8KLmNjLW1kLWNvcHktYnRuLmNjLW1kLWNvcHktb2ssCi5jYy1tZC1jb3B5LWJ0bi5jYy1tZC1jb3B5LW9rOmhvdmVyIHsKICBvcGFjaXR5OiAxOwogIGNvbG9yOiB2YXIoLS12c2NvZGUtY2hhcnRzLWdyZWVuLCB2YXIoLS12c2NvZGUtdGVzdGluZy1pY29uUGFzc2VkLCAjODlkMTg1KSk7CiAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7Cn0KLyogV2hvbGUtY29udmVyc2F0aW9uIGNvcHk6IGEgc2luZ2xlIGZsb2F0aW5nIGljb24gcGlubmVkIHRvIHRoZSB0b3AtcmlnaHQgY29ybmVyLAogICBjbGVhciBvZiB0aGUgY2hhdCBpbnB1dCBhdCB0aGUgYm90dG9tLiBTaG93biBvbmx5IHdoaWxlIGEgY29udmVyc2F0aW9uIGlzIG9wZW4KICAgKHRoZSBJSUZFIGFkZHMvcmVtb3ZlcyBpdCkuIE51ZGdlIHRvcC9yaWdodCBoZXJlIGlmIGl0IGNyb3dkcyB0aGUgc3RpY2t5IGhlYWRlci4gKi8KLmNjLW1kLWNvcHktY29udmVyc2F0aW9uIHsKICBwb3NpdGlvbjogZml4ZWQ7CiAgdG9wOiAyNnB4OwogIHJpZ2h0OiA0cHg7CiAgei1pbmRleDogMzA7CiAgZGlzcGxheTogaW5saW5lLWZsZXg7CiAgcGFkZGluZzogMnB4OwogIGJhY2tncm91bmQ6IHZhcigtLXZzY29kZS1lZGl0b3JXaWRnZXQtYmFja2dyb3VuZCk7CiAgYm9yZGVyOiAxcHggc29saWQgdmFyKC0tdnNjb2RlLXdpZGdldC1ib3JkZXIsIHRyYW5zcGFyZW50KTsKICBib3JkZXItcmFkaXVzOiA2cHg7CiAgb3BhY2l0eTogMC44NTsKfQouY2MtbWQtY29weS1jb252ZXJzYXRpb24gLmNjLW1kLWNvcHkgewogIG1hcmdpbi1sZWZ0OiAwOwp9Ci5jYy1tZC1jb3B5LWNvbnZlcnNhdGlvbjpob3ZlciB7CiAgb3BhY2l0eTogMTsKfQo=").decode("utf-8")
# <<<CCWA-MD-COPY-EMBED<<<
_BLOCK_RE = re.compile(r"\n?" + re.escape(OPEN) + r".*?" + re.escape(CLOSE) + r"\n?", re.S)
DISCOVERY_GLOBS = [
os.path.expanduser("~/.vscode/extensions/anthropic.claude-code-*/webview/index.js"),
os.path.expanduser("~/.vscode-server/extensions/anthropic.claude-code-*/webview/index.js"),
os.path.expanduser("~/.vscode-insiders/extensions/anthropic.claude-code-*/webview/index.js"),
os.path.expanduser("~/.vscode-server-insiders/extensions/anthropic.claude-code-*/webview/index.js"),
"/home/*/.vscode-server/extensions/anthropic.claude-code-*/webview/index.js",
]
def discover():
found = set()
for pat in DISCOVERY_GLOBS:
for p in glob.glob(pat):
found.add(os.path.realpath(p))
return sorted(found)
def payload_for(path):
"""index.css -> the CSS block; everything else (index.js) -> the JS block."""
return INJECT_CSS if path.endswith(".css") else INJECT_JS
def write_atomic_preserving_metadata(path, text):
st = os.stat(path)
directory = os.path.dirname(path) or "."
basename = os.path.basename(path)
fd, tmp = tempfile.mkstemp(prefix="." + basename + ".", suffix=".tmp", dir=directory)
try:
with os.fdopen(fd, "w", encoding="utf-8", newline="") as f:
f.write(text)
f.flush()
os.fsync(f.fileno())
try:
os.chown(tmp, st.st_uid, st.st_gid)
except (AttributeError, PermissionError, OSError):
pass
shutil.copystat(path, tmp)
os.replace(tmp, path)
tmp = None
finally:
if tmp is not None:
try:
os.unlink(tmp)
except FileNotFoundError:
pass
def patch_file(path, payload):
with open(path, "r", encoding="utf-8", newline="") as f:
data = f.read()
if OPEN in data:
return "already-patched"
if not payload.strip():
return "no-payload (run tools/gen-embeds)"
backup = path + BACKUP_SUFFIX
if not os.path.exists(backup):
with open(backup, "w", encoding="utf-8", newline="") as b:
b.write(data)
block = OPEN + "\n" + payload.rstrip("\n") + "\n" + CLOSE
write_atomic_preserving_metadata(path, data + "\n" + block + "\n")
return "PATCHED"
def revert_file(path):
with open(path, "r", encoding="utf-8", newline="") as f:
data = f.read()
if OPEN not in data:
return "not-patched"
write_atomic_preserving_metadata(path, _BLOCK_RE.sub("", data, count=1))
return "REVERTED"
def siblings(js_path):
"""Given a .../webview/index.js, also target the sibling index.css."""
targets = [js_path]
css = os.path.join(os.path.dirname(js_path), "index.css")
if os.path.isfile(css):
targets.append(css)
return targets
def main(argv):
revert = "--revert" in argv
explicit = [a for a in argv if not a.startswith("--")]
if explicit:
# An explicit .../webview/index.js expands to its index.css sibling too, so
# `add-md-copy.py .../index.js` patches BOTH files (matching auto-discovery
# and the index.js+index.css architecture). An explicit index.css (or a
# webview dir, resolved by siblings() to js+css) stays as given.
targets = []
for p in explicit:
rp = os.path.realpath(p)
if os.path.basename(rp) == "index.js":
targets.extend(siblings(rp))
elif os.path.isdir(rp):
targets.extend(siblings(os.path.join(rp, "index.js")))
else:
targets.append(rp)
seen = set()
targets = [t for t in targets if not (t in seen or seen.add(t))]
else:
targets = []
for js in discover():
targets.extend(siblings(js))
if not targets:
print("No Claude Code extension webview found.")
return 1
action = (lambda p: revert_file(p)) if revert else (lambda p: patch_file(p, payload_for(p)))
print(("Reverting" if revert else "Patching") + " %d file(s):\n" % len(targets))
changed = 0
for t in targets:
try:
status = action(t)
except OSError as e:
status = "ERROR: %s" % e
if status in ("PATCHED", "REVERTED"):
changed += 1
print(" [%s] %s" % (status, t))
print("\n%d file(s) changed." % changed)
if changed:
print('Reload the webview to apply: Command Palette -> "Developer: Reload Window".')
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))