@kubohiroya/turbowarp-plus-editor-git 0.0.0-stage → 0.8.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/LICENSE +373 -0
- package/README.ja.md +121 -0
- package/README.md +43 -2
- package/THIRD_PARTY_NOTICES.md +5 -0
- package/dist/THIRD_PARTY_NOTICES.md +1186 -0
- package/dist/block-diff-location.d.ts +22 -0
- package/dist/block-diff-preview.d.ts +33 -0
- package/dist/browser.d.ts +4 -0
- package/dist/connection-settings.d.ts +35 -0
- package/dist/file-diff-view.d.ts +18 -0
- package/dist/filesystem.d.ts +89 -0
- package/dist/github-pull-requests.d.ts +38 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +3563 -0
- package/dist/messages.d.ts +112 -0
- package/dist/mutation-fs.d.ts +58 -0
- package/dist/objectSpread2-Dkd68nJH.js +101 -0
- package/dist/project-asset-paths-KV715791.js +761 -0
- package/dist/project-asset-paths.d.ts +12 -0
- package/dist/project-assets.d.ts +19 -0
- package/dist/project-source-diff.d.ts +26 -0
- package/dist/project-source-diff.js +172 -0
- package/dist/project-source-patch.d.ts +39 -0
- package/dist/project-source-review-model.d.ts +23 -0
- package/dist/project-source-review.d.ts +38 -0
- package/dist/pull-request-panel.d.ts +8 -0
- package/dist/remote-operations.d.ts +5 -0
- package/dist/repository-BQkADJmK.js +17280 -0
- package/dist/repository.d.ts +71 -0
- package/dist/repository.js +1 -0
- package/dist/scratch-block-diff-renderer-xS8OYsRl.js +1830 -0
- package/dist/scratch-block-diff-renderer.d.ts +128 -0
- package/dist/smart-http-BmHEkE7K.js +303 -0
- package/dist/smart-http.d.ts +60 -0
- package/dist/smart-http.js +1 -0
- package/dist/style.css +138 -0
- package/package.json +65 -4
- package/src/block-diff-location.ts +63 -0
- package/src/block-diff-preview.tsx +117 -0
- package/src/browser.ts +5 -0
- package/src/connection-settings.tsx +103 -0
- package/src/file-diff-view.tsx +44 -0
- package/src/filesystem.ts +125 -0
- package/src/github-pull-requests.ts +229 -0
- package/src/index.tsx +352 -0
- package/src/messages.ts +64 -0
- package/src/mutation-fs.ts +204 -0
- package/src/project-asset-paths.ts +33 -0
- package/src/project-assets.ts +66 -0
- package/src/project-source-diff.css +108 -0
- package/src/project-source-diff.tsx +139 -0
- package/src/project-source-patch.ts +126 -0
- package/src/project-source-review-model.ts +116 -0
- package/src/project-source-review.tsx +250 -0
- package/src/pull-request-panel.tsx +134 -0
- package/src/remote-operations.ts +90 -0
- package/src/repository.ts +364 -0
- package/src/scratch-block-diff-renderer.ts +331 -0
- package/src/smart-http.ts +190 -0
- package/src/style.css +29 -0
- package/src/styles.d.ts +1 -0
- package/tsconfig.json +18 -0
- package/vite.config.ts +26 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { BlockChangeKind, BlockPart, BlockSide, BlockTable } from './project-source-patch.js';
|
|
2
|
+
import type { DiffSvgBlock } from './block-diff-location.js';
|
|
3
|
+
interface BlockWorkspace {
|
|
4
|
+
dispose(): void;
|
|
5
|
+
markFocused(): void;
|
|
6
|
+
getBlocksBoundingBox(): {
|
|
7
|
+
x?: number;
|
|
8
|
+
y?: number;
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
};
|
|
12
|
+
getBlockById(id: string): DiffSvgBlock | null;
|
|
13
|
+
options?: {
|
|
14
|
+
pathToMedia?: string;
|
|
15
|
+
zoomOptions?: {
|
|
16
|
+
startScale?: number;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
scale?: number;
|
|
20
|
+
scrollX?: number;
|
|
21
|
+
scrollY?: number;
|
|
22
|
+
translate?(x: number, y: number): void;
|
|
23
|
+
getMetrics?(): {
|
|
24
|
+
absoluteLeft?: number;
|
|
25
|
+
absoluteTop?: number;
|
|
26
|
+
} | null;
|
|
27
|
+
scrollbar?: {
|
|
28
|
+
resize(): void;
|
|
29
|
+
} | null;
|
|
30
|
+
}
|
|
31
|
+
interface InjectOptions {
|
|
32
|
+
readOnly: true;
|
|
33
|
+
sounds: false;
|
|
34
|
+
media?: string;
|
|
35
|
+
scrollbars?: boolean;
|
|
36
|
+
zoom?: {
|
|
37
|
+
controls: boolean;
|
|
38
|
+
wheel: boolean;
|
|
39
|
+
startScale: number;
|
|
40
|
+
maxScale: number;
|
|
41
|
+
minScale: number;
|
|
42
|
+
scaleSpeed: number;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export interface ScratchBlocksPort {
|
|
46
|
+
inject(container: HTMLElement, options: InjectOptions): BlockWorkspace;
|
|
47
|
+
svgResize(workspace: BlockWorkspace): void;
|
|
48
|
+
getMainWorkspace(): BlockWorkspace | null;
|
|
49
|
+
mainWorkspace: BlockWorkspace | null;
|
|
50
|
+
Events: {
|
|
51
|
+
disable(): void;
|
|
52
|
+
enable(): void;
|
|
53
|
+
};
|
|
54
|
+
Blocks: Record<string, unknown>;
|
|
55
|
+
defineBlocksWithJsonArray?(definitions: Record<string, unknown>[]): void;
|
|
56
|
+
OUTPUT_SHAPE_ROUND?: number;
|
|
57
|
+
Xml: {
|
|
58
|
+
textToDom(xml: string): Element;
|
|
59
|
+
domToWorkspace(xml: Element, workspace: BlockWorkspace): unknown;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export interface ScratchBlockDiffRendererOptions {
|
|
63
|
+
getBlockly(): ScratchBlocksPort | Promise<ScratchBlocksPort>;
|
|
64
|
+
showUnregisteredBlocks?: boolean;
|
|
65
|
+
locale?: string;
|
|
66
|
+
deserializeBlocks(blocks: BlockTable): Record<string, {
|
|
67
|
+
id: string;
|
|
68
|
+
topLevel?: boolean;
|
|
69
|
+
}>;
|
|
70
|
+
createBlockContainer(): {
|
|
71
|
+
createBlock(block: {
|
|
72
|
+
id: string;
|
|
73
|
+
}, deferProjectChanged: true): void;
|
|
74
|
+
blockToXML(id: string): string | undefined;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Adds the host's workspace navigation to each preview, as in its own code area: for example the costume
|
|
78
|
+
* thumbnail, a minimap and a row of zoom buttons in the lower right. `watermark` holds the costume thumbnail when
|
|
79
|
+
* the version has one; the host positions it. Without this option, previews keep Scratch Blocks' zoom buttons.
|
|
80
|
+
*/
|
|
81
|
+
attachNavigation?(workspace: unknown, blockly: ScratchBlocksPort, watermark?: HTMLElement): {
|
|
82
|
+
dispose(): void;
|
|
83
|
+
} | null | undefined;
|
|
84
|
+
}
|
|
85
|
+
export interface ScriptBlockMark {
|
|
86
|
+
id: string;
|
|
87
|
+
kind: BlockChangeKind;
|
|
88
|
+
parts: readonly BlockPart[];
|
|
89
|
+
}
|
|
90
|
+
/** Position and zoom of one preview, in Scratch Blocks workspace terms. */
|
|
91
|
+
export interface BlockPreviewViewport {
|
|
92
|
+
scale: number;
|
|
93
|
+
x: number;
|
|
94
|
+
y: number;
|
|
95
|
+
}
|
|
96
|
+
/** Lets several previews of one comparison share their zoom, scroll position and height. */
|
|
97
|
+
export interface BlockPreviewView {
|
|
98
|
+
/** The zoom and frame height at which this preview shows all of its blocks. */
|
|
99
|
+
readonly fit: {
|
|
100
|
+
scale: number;
|
|
101
|
+
height: number;
|
|
102
|
+
};
|
|
103
|
+
/** Applies a zoom and frame height, scrolling to the start of the blocks. */
|
|
104
|
+
layout(fit: {
|
|
105
|
+
scale: number;
|
|
106
|
+
height: number;
|
|
107
|
+
}): void;
|
|
108
|
+
viewport(): BlockPreviewViewport;
|
|
109
|
+
setViewport(viewport: BlockPreviewViewport): void;
|
|
110
|
+
/** Calls `listener` after the user scrolls or zooms this preview. */
|
|
111
|
+
onChange(listener: () => void): () => void;
|
|
112
|
+
}
|
|
113
|
+
export type ProjectBlockRendering = (() => void) | {
|
|
114
|
+
dispose(): void;
|
|
115
|
+
view?: BlockPreviewView;
|
|
116
|
+
} | undefined;
|
|
117
|
+
export type ProjectBlockRenderer = (args: BlockSide & {
|
|
118
|
+
container: HTMLElement;
|
|
119
|
+
withContext: boolean;
|
|
120
|
+
parts?: readonly BlockPart[];
|
|
121
|
+
marks?: readonly ScriptBlockMark[];
|
|
122
|
+
signal: AbortSignal;
|
|
123
|
+
/** The costume thumbnail element of this version, placed in the preview's lower right by the host navigation. */
|
|
124
|
+
watermark?: HTMLElement;
|
|
125
|
+
}) => Promise<ProjectBlockRendering>;
|
|
126
|
+
/** Use the host's Scratch VM serializer and Scratch Blocks definitions in an isolated workspace. */
|
|
127
|
+
export declare function createScratchBlocksDiffRenderer(options: ScratchBlockDiffRendererOptions): ProjectBlockRenderer;
|
|
128
|
+
export {};
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { n as init_objectSpread2, t as _objectSpread2 } from "./objectSpread2-Dkd68nJH.js";
|
|
2
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/asyncIterator.js
|
|
3
|
+
function _asyncIterator(r) {
|
|
4
|
+
var n, t, o, e = 2;
|
|
5
|
+
for ("undefined" != typeof Symbol && (t = Symbol.asyncIterator, o = Symbol.iterator); e--;) {
|
|
6
|
+
if (t && null != (n = r[t])) return n.call(r);
|
|
7
|
+
if (o && null != (n = r[o])) return new AsyncFromSyncIterator(n.call(r));
|
|
8
|
+
t = "@@asyncIterator", o = "@@iterator";
|
|
9
|
+
}
|
|
10
|
+
throw new TypeError("Object is not async iterable");
|
|
11
|
+
}
|
|
12
|
+
function AsyncFromSyncIterator(r) {
|
|
13
|
+
function AsyncFromSyncIteratorContinuation(r) {
|
|
14
|
+
if (Object(r) !== r) return Promise.reject(/* @__PURE__ */ new TypeError(r + " is not an object."));
|
|
15
|
+
var n = r.done;
|
|
16
|
+
return Promise.resolve(r.value).then(function(r) {
|
|
17
|
+
return {
|
|
18
|
+
value: r,
|
|
19
|
+
done: n
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return AsyncFromSyncIterator = function AsyncFromSyncIterator(r) {
|
|
24
|
+
this.s = r, this.n = r.next;
|
|
25
|
+
}, AsyncFromSyncIterator.prototype = {
|
|
26
|
+
s: null,
|
|
27
|
+
n: null,
|
|
28
|
+
next: function next() {
|
|
29
|
+
return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments));
|
|
30
|
+
},
|
|
31
|
+
"return": function _return(r) {
|
|
32
|
+
var n = this.s["return"];
|
|
33
|
+
return void 0 === n ? Promise.resolve({
|
|
34
|
+
value: r,
|
|
35
|
+
done: !0
|
|
36
|
+
}) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments));
|
|
37
|
+
},
|
|
38
|
+
"throw": function _throw(r) {
|
|
39
|
+
var n = this.s["throw"];
|
|
40
|
+
return void 0 === n ? Promise.reject(r) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments));
|
|
41
|
+
}
|
|
42
|
+
}, new AsyncFromSyncIterator(r);
|
|
43
|
+
}
|
|
44
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/OverloadYield.js
|
|
45
|
+
function _OverloadYield(e, d) {
|
|
46
|
+
this.v = e, this.k = d;
|
|
47
|
+
}
|
|
48
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/awaitAsyncGenerator.js
|
|
49
|
+
function _awaitAsyncGenerator(e) {
|
|
50
|
+
return new _OverloadYield(e, 0);
|
|
51
|
+
}
|
|
52
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/wrapAsyncGenerator.js
|
|
53
|
+
function _wrapAsyncGenerator(e) {
|
|
54
|
+
return function() {
|
|
55
|
+
return new AsyncGenerator(e.apply(this, arguments));
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function AsyncGenerator(e) {
|
|
59
|
+
var r, t;
|
|
60
|
+
function resume(r, t) {
|
|
61
|
+
try {
|
|
62
|
+
var n = e[r](t), o = n.value, u = o instanceof _OverloadYield;
|
|
63
|
+
Promise.resolve(u ? o.v : o).then(function(t) {
|
|
64
|
+
if (u) {
|
|
65
|
+
var i = "return" === r ? "return" : "next";
|
|
66
|
+
if (!o.k || t.done) return resume(i, t);
|
|
67
|
+
t = e[i](t).value;
|
|
68
|
+
}
|
|
69
|
+
settle(n.done ? "return" : "normal", t);
|
|
70
|
+
}, function(e) {
|
|
71
|
+
resume("throw", e);
|
|
72
|
+
});
|
|
73
|
+
} catch (e) {
|
|
74
|
+
settle("throw", e);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function settle(e, n) {
|
|
78
|
+
switch (e) {
|
|
79
|
+
case "return":
|
|
80
|
+
r.resolve({
|
|
81
|
+
value: n,
|
|
82
|
+
done: !0
|
|
83
|
+
});
|
|
84
|
+
break;
|
|
85
|
+
case "throw":
|
|
86
|
+
r.reject(n);
|
|
87
|
+
break;
|
|
88
|
+
default: r.resolve({
|
|
89
|
+
value: n,
|
|
90
|
+
done: !1
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
(r = r.next) ? resume(r.key, r.arg) : t = null;
|
|
94
|
+
}
|
|
95
|
+
this._invoke = function(e, n) {
|
|
96
|
+
return new Promise(function(o, u) {
|
|
97
|
+
var i = {
|
|
98
|
+
key: e,
|
|
99
|
+
arg: n,
|
|
100
|
+
resolve: o,
|
|
101
|
+
reject: u,
|
|
102
|
+
next: null
|
|
103
|
+
};
|
|
104
|
+
t ? t = t.next = i : (r = t = i, resume(e, n));
|
|
105
|
+
});
|
|
106
|
+
}, "function" != typeof e["return"] && (this["return"] = void 0);
|
|
107
|
+
}
|
|
108
|
+
AsyncGenerator.prototype["function" == typeof Symbol && Symbol.asyncIterator || "@@asyncIterator"] = function() {
|
|
109
|
+
return this;
|
|
110
|
+
}, AsyncGenerator.prototype.next = function(e) {
|
|
111
|
+
return this._invoke("next", e);
|
|
112
|
+
}, AsyncGenerator.prototype["throw"] = function(e) {
|
|
113
|
+
return this._invoke("throw", e);
|
|
114
|
+
}, AsyncGenerator.prototype["return"] = function(e) {
|
|
115
|
+
return this._invoke("return", e);
|
|
116
|
+
};
|
|
117
|
+
// src/smart-http.ts
|
|
118
|
+
init_objectSpread2();
|
|
119
|
+
var MAX_GIT_REQUEST_BYTES = 33554432;
|
|
120
|
+
var proxyCodes = {
|
|
121
|
+
400: ["BAD_REQUEST"],
|
|
122
|
+
401: [
|
|
123
|
+
"SESSION_REQUIRED",
|
|
124
|
+
"SESSION_EXPIRED",
|
|
125
|
+
"REAUTH_REQUIRED"
|
|
126
|
+
],
|
|
127
|
+
403: ["FORBIDDEN"],
|
|
128
|
+
409: ["REDIRECT_REJECTED"],
|
|
129
|
+
411: ["LENGTH_REQUIRED"],
|
|
130
|
+
413: ["PAYLOAD_TOO_LARGE"],
|
|
131
|
+
429: ["RATE_LIMITED"],
|
|
132
|
+
502: ["UPSTREAM_FAILURE"],
|
|
133
|
+
504: ["UPSTREAM_TIMEOUT"]
|
|
134
|
+
};
|
|
135
|
+
var GitSmartHttpError = class extends Error {
|
|
136
|
+
constructor(code, statusCode, requestId) {
|
|
137
|
+
super(code);
|
|
138
|
+
this.code = code;
|
|
139
|
+
this.statusCode = statusCode;
|
|
140
|
+
this.requestId = requestId;
|
|
141
|
+
this.name = "GitSmartHttpError";
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
function remoteUrl(remote) {
|
|
145
|
+
const match = /^https:\/\/github\.com\/([A-Za-z0-9][A-Za-z0-9-]*)\/([A-Za-z0-9_.-]+?)(?:\.git)?$/u.exec(remote);
|
|
146
|
+
if (!match || match[0] !== remote || [
|
|
147
|
+
".",
|
|
148
|
+
"..",
|
|
149
|
+
".git"
|
|
150
|
+
].includes(match[2].toLowerCase())) throw new GitSmartHttpError("INVALID_REMOTE");
|
|
151
|
+
return `https://github.com/${match[1]}/${match[2]}.git`;
|
|
152
|
+
}
|
|
153
|
+
function checkConnection({ mode, proxyOrigin }) {
|
|
154
|
+
const url = URL.parse(proxyOrigin);
|
|
155
|
+
if (!url || url.origin !== proxyOrigin || (mode === "desktop" ? !/^http:\/\/127\.0\.0\.1:[1-9][0-9]{0,4}$/u.test(proxyOrigin) : mode !== "cloudflare" || url.protocol !== "https:")) throw new GitSmartHttpError("INVALID_CONNECTION");
|
|
156
|
+
}
|
|
157
|
+
function checkAbort(signal) {
|
|
158
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) throw new GitSmartHttpError("ABORTED");
|
|
159
|
+
}
|
|
160
|
+
async function boundedBody(source, limit, signal) {
|
|
161
|
+
const parts = [];
|
|
162
|
+
let size = 0;
|
|
163
|
+
var _iteratorAbruptCompletion = false;
|
|
164
|
+
var _didIteratorError = false;
|
|
165
|
+
var _iteratorError;
|
|
166
|
+
try {
|
|
167
|
+
for (var _iterator = _asyncIterator(source), _step; _iteratorAbruptCompletion = !(_step = await _iterator.next()).done; _iteratorAbruptCompletion = false) {
|
|
168
|
+
const bytes = _step.value;
|
|
169
|
+
checkAbort(signal);
|
|
170
|
+
size += bytes.byteLength;
|
|
171
|
+
if (size > limit) throw new GitSmartHttpError("PAYLOAD_TOO_LARGE");
|
|
172
|
+
parts.push(bytes.slice());
|
|
173
|
+
}
|
|
174
|
+
} catch (err) {
|
|
175
|
+
_didIteratorError = true;
|
|
176
|
+
_iteratorError = err;
|
|
177
|
+
} finally {
|
|
178
|
+
try {
|
|
179
|
+
if (_iteratorAbruptCompletion && _iterator.return != null) await _iterator.return();
|
|
180
|
+
} finally {
|
|
181
|
+
if (_didIteratorError) throw _iteratorError;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return new Blob(parts);
|
|
185
|
+
}
|
|
186
|
+
function responseBytes(_x, _x2, _x3) {
|
|
187
|
+
return _responseBytes.apply(this, arguments);
|
|
188
|
+
}
|
|
189
|
+
function _responseBytes() {
|
|
190
|
+
_responseBytes = _wrapAsyncGenerator(function* (body, code, signal) {
|
|
191
|
+
const reader = body.getReader();
|
|
192
|
+
try {
|
|
193
|
+
for (;;) {
|
|
194
|
+
const { done, value } = yield _awaitAsyncGenerator(reader.read());
|
|
195
|
+
if (done) return;
|
|
196
|
+
yield value;
|
|
197
|
+
}
|
|
198
|
+
} catch (_unused) {
|
|
199
|
+
if (code !== "PUSH_OUTCOME_UNKNOWN") checkAbort(signal);
|
|
200
|
+
throw new GitSmartHttpError(code);
|
|
201
|
+
} finally {
|
|
202
|
+
yield _awaitAsyncGenerator(reader.cancel().catch(() => {}));
|
|
203
|
+
reader.releaseLock();
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
return _responseBytes.apply(this, arguments);
|
|
207
|
+
}
|
|
208
|
+
async function proxyError(response, writing) {
|
|
209
|
+
var _allowed$, _response$headers$get;
|
|
210
|
+
const status = response.status;
|
|
211
|
+
const allowed = proxyCodes[status];
|
|
212
|
+
let code = (_allowed$ = allowed === null || allowed === void 0 ? void 0 : allowed[0]) !== null && _allowed$ !== void 0 ? _allowed$ : "INVALID_RESPONSE";
|
|
213
|
+
let requestId;
|
|
214
|
+
if (response.body && ((_response$headers$get = response.headers.get("content-type")) === null || _response$headers$get === void 0 ? void 0 : _response$headers$get.split(";")[0]) === "application/json") try {
|
|
215
|
+
const body = await boundedBody(responseBytes(response.body, "INVALID_RESPONSE"), 4096);
|
|
216
|
+
const parsed = JSON.parse(await body.text());
|
|
217
|
+
if (writing && status === 409 && (parsed === null || parsed === void 0 ? void 0 : parsed.code) === "PUSH_DUPLICATE") code = "PUSH_OUTCOME_UNKNOWN";
|
|
218
|
+
else if (allowed === null || allowed === void 0 ? void 0 : allowed.includes(parsed === null || parsed === void 0 ? void 0 : parsed.code)) code = parsed.code;
|
|
219
|
+
if (typeof (parsed === null || parsed === void 0 ? void 0 : parsed.requestId) === "string" && /^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/iu.test(parsed.requestId)) requestId = parsed.requestId;
|
|
220
|
+
} catch (_unused2) {}
|
|
221
|
+
else {
|
|
222
|
+
var _response$body;
|
|
223
|
+
await ((_response$body = response.body) === null || _response$body === void 0 ? void 0 : _response$body.cancel().catch(() => {}));
|
|
224
|
+
}
|
|
225
|
+
if (writing && (!allowed || status >= 500)) code = "PUSH_OUTCOME_UNKNOWN";
|
|
226
|
+
return new GitSmartHttpError(code, status, requestId);
|
|
227
|
+
}
|
|
228
|
+
function createGitSmartHttp(options) {
|
|
229
|
+
const url = remoteUrl(options.remote);
|
|
230
|
+
const connection = _objectSpread2({}, options.connection);
|
|
231
|
+
checkConnection(connection);
|
|
232
|
+
const { getSession, maxRequestBytes = MAX_GIT_REQUEST_BYTES, signal: operationSignal, fetch: send = fetch } = options;
|
|
233
|
+
if (!Number.isSafeInteger(maxRequestBytes) || maxRequestBytes <= 0 || maxRequestBytes > 33554432) throw new GitSmartHttpError("INVALID_CONNECTION");
|
|
234
|
+
const proxyPath = connection.proxyOrigin + "/v1/git" + url.slice(18);
|
|
235
|
+
const request = async ({ url: requested, method = "GET", body, signal }) => {
|
|
236
|
+
var _session$connection;
|
|
237
|
+
const path = requested.startsWith(url + "/") ? requested.slice(url.length) : "";
|
|
238
|
+
const discovery = method === "GET" && !body;
|
|
239
|
+
const rpc = method === "POST" && Boolean(body);
|
|
240
|
+
const service = ["git-upload-pack", "git-receive-pack"].find((name) => discovery && path === `/info/refs?service=${name}` || rpc && path === `/${name}`);
|
|
241
|
+
if (!service) throw new GitSmartHttpError("INVALID_REQUEST");
|
|
242
|
+
const abort = signal && operationSignal ? AbortSignal.any([signal, operationSignal]) : signal !== null && signal !== void 0 ? signal : operationSignal;
|
|
243
|
+
checkAbort(abort);
|
|
244
|
+
const payload = body ? await boundedBody(body, maxRequestBytes, abort) : void 0;
|
|
245
|
+
checkAbort(abort);
|
|
246
|
+
let session;
|
|
247
|
+
try {
|
|
248
|
+
session = await getSession();
|
|
249
|
+
} catch (_unused3) {
|
|
250
|
+
checkAbort(abort);
|
|
251
|
+
throw new GitSmartHttpError("SESSION_UNAVAILABLE");
|
|
252
|
+
}
|
|
253
|
+
checkAbort(abort);
|
|
254
|
+
if (!session) throw new GitSmartHttpError("SESSION_REQUIRED");
|
|
255
|
+
if (!Number.isFinite(session.expiresAt) || session.expiresAt <= Date.now()) throw new GitSmartHttpError("SESSION_EXPIRED");
|
|
256
|
+
if (((_session$connection = session.connection) === null || _session$connection === void 0 ? void 0 : _session$connection.mode) !== connection.mode || session.connection.proxyOrigin !== connection.proxyOrigin || typeof session.bearer !== "string" || !/^[A-Za-z0-9._~+\/-]+=*$/u.test(session.bearer)) throw new GitSmartHttpError("INVALID_SESSION");
|
|
257
|
+
const contentType = `application/x-${service}-${discovery ? "advertisement" : "result"}`;
|
|
258
|
+
const headers = new Headers({
|
|
259
|
+
Authorization: `Bearer ${session.bearer}`,
|
|
260
|
+
Accept: contentType
|
|
261
|
+
});
|
|
262
|
+
if (payload) headers.set("Content-Type", `application/x-${service}-request`);
|
|
263
|
+
const writing = rpc && service === "git-receive-pack";
|
|
264
|
+
if (writing) headers.set("Git-Push-Id", crypto.randomUUID());
|
|
265
|
+
let response;
|
|
266
|
+
try {
|
|
267
|
+
response = await send(proxyPath + path, {
|
|
268
|
+
method,
|
|
269
|
+
headers,
|
|
270
|
+
body: payload,
|
|
271
|
+
signal: abort,
|
|
272
|
+
credentials: "omit",
|
|
273
|
+
redirect: "error",
|
|
274
|
+
cache: "no-store",
|
|
275
|
+
referrerPolicy: "no-referrer"
|
|
276
|
+
});
|
|
277
|
+
} catch (_unused4) {
|
|
278
|
+
if (writing) throw new GitSmartHttpError("PUSH_OUTCOME_UNKNOWN");
|
|
279
|
+
checkAbort(abort);
|
|
280
|
+
throw new GitSmartHttpError("NETWORK_ERROR");
|
|
281
|
+
}
|
|
282
|
+
if (response.status !== 200) throw await proxyError(response, writing);
|
|
283
|
+
if (!response.body || response.headers.get("content-type") !== contentType) {
|
|
284
|
+
var _response$body2;
|
|
285
|
+
await ((_response$body2 = response.body) === null || _response$body2 === void 0 ? void 0 : _response$body2.cancel().catch(() => {}));
|
|
286
|
+
throw new GitSmartHttpError(writing ? "PUSH_OUTCOME_UNKNOWN" : "INVALID_RESPONSE");
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
url: requested,
|
|
290
|
+
method,
|
|
291
|
+
headers: { "content-type": contentType },
|
|
292
|
+
statusCode: 200,
|
|
293
|
+
statusMessage: "OK",
|
|
294
|
+
body: responseBytes(response.body, writing ? "PUSH_OUTCOME_UNKNOWN" : "NETWORK_ERROR", abort)
|
|
295
|
+
};
|
|
296
|
+
};
|
|
297
|
+
return {
|
|
298
|
+
url,
|
|
299
|
+
corsProxy: "",
|
|
300
|
+
http: { request }
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
export { _OverloadYield as a, _wrapAsyncGenerator as i, MAX_GIT_REQUEST_BYTES as n, _asyncIterator as o, createGitSmartHttp as r, GitSmartHttpError as t };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export declare const MAX_GIT_REQUEST_BYTES: number;
|
|
2
|
+
type Connection = Readonly<{
|
|
3
|
+
mode: 'desktop' | 'cloudflare';
|
|
4
|
+
proxyOrigin: string;
|
|
5
|
+
}>;
|
|
6
|
+
type Session = Readonly<{
|
|
7
|
+
connection: Connection;
|
|
8
|
+
bearer: string;
|
|
9
|
+
expiresAt: number;
|
|
10
|
+
}>;
|
|
11
|
+
export interface GitSmartHttpOptions {
|
|
12
|
+
readonly remote: string;
|
|
13
|
+
readonly connection: Connection;
|
|
14
|
+
readonly getSession: () => Promise<Session | null>;
|
|
15
|
+
readonly maxRequestBytes?: number;
|
|
16
|
+
readonly signal?: AbortSignal;
|
|
17
|
+
readonly fetch?: typeof fetch;
|
|
18
|
+
}
|
|
19
|
+
type Request = {
|
|
20
|
+
url: string;
|
|
21
|
+
method?: string;
|
|
22
|
+
body?: AsyncIterable<Uint8Array>;
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
};
|
|
25
|
+
declare const proxyCodes: {
|
|
26
|
+
readonly 400: readonly ["BAD_REQUEST"];
|
|
27
|
+
readonly 401: readonly ["SESSION_REQUIRED", "SESSION_EXPIRED", "REAUTH_REQUIRED"];
|
|
28
|
+
readonly 403: readonly ["FORBIDDEN"];
|
|
29
|
+
readonly 409: readonly ["REDIRECT_REJECTED"];
|
|
30
|
+
readonly 411: readonly ["LENGTH_REQUIRED"];
|
|
31
|
+
readonly 413: readonly ["PAYLOAD_TOO_LARGE"];
|
|
32
|
+
readonly 429: readonly ["RATE_LIMITED"];
|
|
33
|
+
readonly 502: readonly ["UPSTREAM_FAILURE"];
|
|
34
|
+
readonly 504: readonly ["UPSTREAM_TIMEOUT"];
|
|
35
|
+
};
|
|
36
|
+
type ProxyErrorCode = (typeof proxyCodes)[keyof typeof proxyCodes][number];
|
|
37
|
+
export type GitSmartHttpErrorCode = ProxyErrorCode | 'INVALID_REMOTE' | 'INVALID_REQUEST' | 'INVALID_CONNECTION' | 'INVALID_SESSION' | 'SESSION_UNAVAILABLE' | 'ABORTED' | 'NETWORK_ERROR' | 'INVALID_RESPONSE' | 'PUSH_OUTCOME_UNKNOWN';
|
|
38
|
+
export declare class GitSmartHttpError extends Error {
|
|
39
|
+
readonly code: GitSmartHttpErrorCode;
|
|
40
|
+
readonly statusCode?: number | undefined;
|
|
41
|
+
readonly requestId?: string | undefined;
|
|
42
|
+
constructor(code: GitSmartHttpErrorCode, statusCode?: number | undefined, requestId?: string | undefined);
|
|
43
|
+
}
|
|
44
|
+
export declare function createGitSmartHttp(options: GitSmartHttpOptions): {
|
|
45
|
+
url: string;
|
|
46
|
+
corsProxy: "";
|
|
47
|
+
http: {
|
|
48
|
+
request: ({ url: requested, method, body, signal }: Request) => Promise<{
|
|
49
|
+
url: string;
|
|
50
|
+
method: string;
|
|
51
|
+
headers: {
|
|
52
|
+
'content-type': string;
|
|
53
|
+
};
|
|
54
|
+
statusCode: number;
|
|
55
|
+
statusMessage: string;
|
|
56
|
+
body: AsyncGenerator<Uint8Array<ArrayBufferLike>, void, unknown>;
|
|
57
|
+
}>;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { t as GitSmartHttpError, n as MAX_GIT_REQUEST_BYTES, r as createGitSmartHttp } from "./smart-http-BmHEkE7K.js";
|
package/dist/style.css
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
.twgit-block-diff {
|
|
2
|
+
color: CanvasText;
|
|
3
|
+
background: Canvas;
|
|
4
|
+
font: 14px/1.5 system-ui, sans-serif;
|
|
5
|
+
container-type: inline-size;
|
|
6
|
+
}
|
|
7
|
+
.twgit-block-diff h2 { margin: 0; font-size: 1.3em; }
|
|
8
|
+
.twgit-block-diff > p { margin: 4px 0 10px; }
|
|
9
|
+
.twgit-block-diff-card {
|
|
10
|
+
border: 1px solid color-mix(in srgb, CanvasText 25%, Canvas);
|
|
11
|
+
border-radius: 8px;
|
|
12
|
+
margin: 12px 0;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
}
|
|
15
|
+
.twgit-block-diff-card > header { padding: 10px 14px; background: color-mix(in srgb, CanvasText 5%, Canvas); }
|
|
16
|
+
.twgit-block-diff-card h3, .twgit-block-diff-card h4 { margin: 0; font-size: 1em; overflow-wrap: anywhere; }
|
|
17
|
+
.twgit-block-diff-card h3 span { margin-inline-end: 6px; color: CanvasText; border-bottom: 3px solid var(--twgit-change); }
|
|
18
|
+
.twgit-block-diff-card p { margin: 4px 0 0; }
|
|
19
|
+
.twgit-block-diff-added { --twgit-change: #25875d; }
|
|
20
|
+
.twgit-block-diff-removed { --twgit-change: #c54a53; }
|
|
21
|
+
.twgit-block-diff-updated { --twgit-change: #635bce; }
|
|
22
|
+
.twgit-block-diff-sides { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
23
|
+
.twgit-block-diff-side { padding: 10px 14px; min-width: 0; }
|
|
24
|
+
.twgit-block-diff-side + .twgit-block-diff-side { border-inline-start: 1px solid color-mix(in srgb, CanvasText 20%, Canvas); }
|
|
25
|
+
/* A preview is a small workspace: it scrolls and zooms inside its frame, which people can make taller. */
|
|
26
|
+
.twgit-block-diff-preview {
|
|
27
|
+
position: relative;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
resize: vertical;
|
|
30
|
+
min-height: 120px;
|
|
31
|
+
max-height: 85vh;
|
|
32
|
+
border: 1px solid color-mix(in srgb, CanvasText 18%, Canvas);
|
|
33
|
+
border-radius: 6px;
|
|
34
|
+
}
|
|
35
|
+
.twgit-block-diff-surface { position: absolute; inset: 0; }
|
|
36
|
+
.twgit-block-diff-watermark { position: absolute; z-index: 2; top: 10px; right: 12px; pointer-events: none; }
|
|
37
|
+
.twgit-block-diff-watermark[data-navigation] { top: auto; right: var(--plus-watermark-right, 12px); bottom: var(--plus-watermark-bottom, 140px); }
|
|
38
|
+
.twgit-block-diff-watermark > img {
|
|
39
|
+
display: block;
|
|
40
|
+
max-width: var(--plus-watermark-size, 48px);
|
|
41
|
+
max-height: var(--plus-watermark-size, 48px);
|
|
42
|
+
opacity: .6;
|
|
43
|
+
}
|
|
44
|
+
.twgit-block-diff-link { display: block; padding: 6px 12px 0; }
|
|
45
|
+
/* These markers also apply to the live Editor workspace returned by the host. */
|
|
46
|
+
.twgit-changed-block > .blocklyPath { stroke: var(--twgit-change, #635bce); stroke-width: 2.5px; }
|
|
47
|
+
.twgit-changed-block-part { outline: 2.5px solid #b4510a; outline-offset: 2px; }
|
|
48
|
+
.twgit-block-diff-legend { font-size: .9em; }
|
|
49
|
+
.twgit-block-diff-side > button { margin-top: 8px; }
|
|
50
|
+
.twgit-block-diff-card > label { display: block; padding: 7px 14px 10px; }
|
|
51
|
+
@container (max-width: 440px) {
|
|
52
|
+
.twgit-block-diff-sides { grid-template-columns: minmax(0, 1fr); }
|
|
53
|
+
.twgit-block-diff-side + .twgit-block-diff-side { border-inline-start: 0; border-block-start: 1px solid color-mix(in srgb, CanvasText 20%, Canvas); }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.twgit-review { --twgit-review-line: color-mix(in srgb, CanvasText 18%, Canvas); }
|
|
57
|
+
.twgit-review-overview { border-bottom: 1px solid var(--twgit-review-line); padding-bottom: 14px; }
|
|
58
|
+
.twgit-review-overview > p:first-child { margin: 0 0 5px; color: color-mix(in srgb, CanvasText 70%, Canvas); font-weight: 600; }
|
|
59
|
+
.twgit-review-overview h2 { font-size: 1.65em; }
|
|
60
|
+
.twgit-review-description { white-space: pre-wrap; overflow-wrap: anywhere; margin: 5px 0; }
|
|
61
|
+
.twgit-review-body summary { cursor: pointer; text-decoration: underline; }
|
|
62
|
+
.twgit-review-overview dl { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0; }
|
|
63
|
+
.twgit-review-overview dl > div { min-width: 90px; padding: 7px 12px; border: 1px solid var(--twgit-review-line); border-radius: 6px; }
|
|
64
|
+
.twgit-review-overview dt { font-size: .85em; }
|
|
65
|
+
.twgit-review-overview dd { margin: 0; font-size: 1.3em; font-weight: 650; }
|
|
66
|
+
.twgit-review-checklist h3, .twgit-review-checklist ul { margin: 0; }
|
|
67
|
+
.twgit-review-checklist ul { padding-inline-start: 22px; }
|
|
68
|
+
.twgit-review-files-title { margin: 13px 0 6px; }
|
|
69
|
+
.twgit-review-file { border: 1px solid var(--twgit-review-line); border-radius: 8px; overflow: hidden; margin-bottom: 10px; }
|
|
70
|
+
.twgit-review-file > header { background: color-mix(in srgb, CanvasText 5%, Canvas); padding: 8px 12px; }
|
|
71
|
+
.twgit-review-file > header h4, .twgit-review-file > header p { margin: 0; overflow-wrap: anywhere; }
|
|
72
|
+
.twgit-review-file > p, .twgit-review-target > p { margin: 6px 12px; }
|
|
73
|
+
.twgit-review-target { padding: 6px 12px 10px; }
|
|
74
|
+
.twgit-review-target h5 { font-size: 1em; margin: 0 0 5px; }
|
|
75
|
+
.twgit-review-target h5 small { margin-inline-start: 6px; font-weight: 400; }
|
|
76
|
+
.twgit-review-script { border: 1px solid var(--twgit-review-line); border-radius: 6px; margin: 4px 0; overflow: hidden; }
|
|
77
|
+
.twgit-review-script > summary { cursor: pointer; padding: 7px 10px; list-style: none; }
|
|
78
|
+
.twgit-review-script > summary::-webkit-details-marker { display: none; }
|
|
79
|
+
.twgit-review-script > summary::before { content: '▸'; margin-inline-end: 7px; }
|
|
80
|
+
.twgit-review-script[open] > summary::before { content: '▾'; }
|
|
81
|
+
.twgit-review-script > summary:focus-visible { outline: 2px solid Highlight; outline-offset: -2px; }
|
|
82
|
+
.twgit-review-script > summary > * { margin-inline-end: 8px; }
|
|
83
|
+
.twgit-review-script[open] > summary { border-bottom: 1px solid var(--twgit-review-line); }
|
|
84
|
+
.twgit-review-script h4 { margin: 0 0 3px; }
|
|
85
|
+
.twgit-review-script .twgit-block-diff-side + .twgit-block-diff-side { border-inline-start: 0; border-block-start: 1px solid var(--twgit-review-line); }
|
|
86
|
+
.twgit-review-script .twgit-block-diff-sides > div + div { border-inline-start: 1px solid var(--twgit-review-line); }
|
|
87
|
+
.twgit-review-status { font-size: .85em; padding: 2px 5px; border: 1px solid var(--twgit-review-line); border-radius: 4px; }
|
|
88
|
+
.twgit-review-checked { display: block; padding: 6px 12px 9px; }
|
|
89
|
+
@container (max-width: 440px) {
|
|
90
|
+
.twgit-review-script .twgit-block-diff-sides > div + div { border-inline-start: 0; border-block-start: 1px solid var(--twgit-review-line); }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.twgit-pr-number { display: flex; flex-wrap: wrap; align-items: end; gap: 6px; margin-bottom: 8px; }
|
|
94
|
+
.twgit-pr-number input { display: block; width: 10em; max-width: 100%; }
|
|
95
|
+
.twgit-pr-paging, .twgit-pr-revision { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
|
96
|
+
.twgit-pr-revision code { overflow-wrap: anywhere; }
|
|
97
|
+
.twgit-review .twgit-block-diff-side h4 { font-size: 1em; }
|
|
98
|
+
|
|
99
|
+
/* Costume (or backdrop) thumbnails in stage and sprite headings. */
|
|
100
|
+
.twgit-review-thumbnails { display: inline-flex; align-items: center; gap: 4px; margin-inline-end: 6px; vertical-align: middle; }
|
|
101
|
+
.twgit-review-thumbnails img {
|
|
102
|
+
width: 30px;
|
|
103
|
+
height: 30px;
|
|
104
|
+
object-fit: contain;
|
|
105
|
+
background: Canvas;
|
|
106
|
+
border: 1px solid var(--twgit-review-line, color-mix(in srgb, CanvasText 18%, Canvas));
|
|
107
|
+
border-radius: 4px;
|
|
108
|
+
}
|
|
109
|
+
:root{--diff-background-color:initial;--diff-text-color:initial;--diff-font-family:Consolas,Courier,monospace;--diff-selection-background-color:#b3d7ff;--diff-selection-text-color:var(--diff-text-color);--diff-gutter-insert-background-color:#d6fedb;--diff-gutter-insert-text-color:var(--diff-text-color);--diff-gutter-delete-background-color:#fadde0;--diff-gutter-delete-text-color:var(--diff-text-color);--diff-gutter-selected-background-color:#fffce0;--diff-gutter-selected-text-color:var(--diff-text-color);--diff-code-insert-background-color:#eaffee;--diff-code-insert-text-color:var(--diff-text-color);--diff-code-delete-background-color:#fdeff0;--diff-code-delete-text-color:var(--diff-text-color);--diff-code-insert-edit-background-color:#c0dc91;--diff-code-insert-edit-text-color:var(--diff-text-color);--diff-code-delete-edit-background-color:#f39ea2;--diff-code-delete-edit-text-color:var(--diff-text-color);--diff-code-selected-background-color:#fffce0;--diff-code-selected-text-color:var(--diff-text-color);--diff-omit-gutter-line-color:#cb2a1d;}.diff{background-color:var(--diff-background-color);border-collapse:collapse;color:var(--diff-text-color);table-layout:fixed;width:100%;}.diff::-moz-selection{background-color:#b3d7ff;background-color:var(--diff-selection-background-color);color:var(--diff-text-color);color:var(--diff-selection-text-color);}.diff::selection{background-color:#b3d7ff;background-color:var(--diff-selection-background-color);color:var(--diff-text-color);color:var(--diff-selection-text-color);}.diff td{padding-bottom:0;padding-top:0;vertical-align:top;}.diff-line{font-family:Consolas,Courier,monospace;font-family:var(--diff-font-family);line-height:1.5;}.diff-gutter>a{color:inherit;display:block;}.diff-gutter{cursor:pointer;padding:0 1ch;text-align:right;-webkit-user-select:none;-moz-user-select:none;user-select:none;}.diff-gutter-insert{background-color:#d6fedb;background-color:var(--diff-gutter-insert-background-color);color:var(--diff-text-color);color:var(--diff-gutter-insert-text-color);}.diff-gutter-delete{background-color:#fadde0;background-color:var(--diff-gutter-delete-background-color);color:var(--diff-text-color);color:var(--diff-gutter-delete-text-color);}.diff-gutter-omit{cursor:default;}.diff-gutter-selected{background-color:#fffce0;background-color:var(--diff-gutter-selected-background-color);color:var(--diff-text-color);color:var(--diff-gutter-selected-text-color);}.diff-code{word-wrap:break-word;padding:0 0 0 .5em;white-space:pre-wrap;word-break:break-all;}.diff-code-edit{color:inherit;}.diff-code-insert{background-color:#eaffee;background-color:var(--diff-code-insert-background-color);color:var(--diff-text-color);color:var(--diff-code-insert-text-color);}.diff-code-insert .diff-code-edit{background-color:#c0dc91;background-color:var(--diff-code-insert-edit-background-color);color:var(--diff-text-color);color:var(--diff-code-insert-edit-text-color);}.diff-code-delete{background-color:#fdeff0;background-color:var(--diff-code-delete-background-color);color:var(--diff-text-color);color:var(--diff-code-delete-text-color);}.diff-code-delete .diff-code-edit{background-color:#f39ea2;background-color:var(--diff-code-delete-edit-background-color);color:var(--diff-text-color);color:var(--diff-code-delete-edit-text-color);}.diff-code-selected{background-color:#fffce0;background-color:var(--diff-code-selected-background-color);color:var(--diff-text-color);color:var(--diff-code-selected-text-color);}.diff-widget-content{vertical-align:top;}.diff-gutter-col{width:7ch;}.diff-gutter-omit{height:0;}.diff-gutter-omit:before{background-color:#cb2a1d;background-color:var(--diff-omit-gutter-line-color);content:" ";display:block;height:100%;margin-left:4.6ch;overflow:hidden;white-space:pre;width:2px;}.diff-decoration{line-height:1.5;-webkit-user-select:none;-moz-user-select:none;user-select:none;}.diff-decoration-content{font-family:Consolas,Courier,monospace;font-family:var(--diff-font-family);padding:0;}.twgit-backdrop { position: fixed; inset: 0; z-index: 65000; background: #0006; display: flex; align-items: center; justify-content: center; }
|
|
110
|
+
.twgit-panel { width: 94vw; height: 90vh; display: flex; flex-direction: column; background: Canvas; color: CanvasText; border: 1px solid GrayText; border-radius: 8px; box-shadow: 0 12px 48px #0005; font: 14px/1.5 system-ui, sans-serif; overflow: hidden; }
|
|
111
|
+
.twgit-panel > header { display: flex; gap: 8px; align-items: center; padding: 10px 16px; border-bottom: 1px solid GrayText; }
|
|
112
|
+
.twgit-panel > header h2 { margin: 0 auto 0 0; font-size: 18px; }
|
|
113
|
+
.twgit-panel h3 { font-size: 14px; margin: 12px 0 5px; }
|
|
114
|
+
.twgit-panel button { color: inherit; background: Canvas; border: 1px solid GrayText; border-radius: 4px; padding: 4px 8px; cursor: pointer; font: inherit; text-align: start; }
|
|
115
|
+
.twgit-panel button:disabled { opacity: .5; cursor: default; }
|
|
116
|
+
.twgit-panel button:focus-visible, .twgit-panel summary:focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }
|
|
117
|
+
.twgit-panel button[aria-pressed="true"] { color: HighlightText; background: Highlight; }
|
|
118
|
+
.twgit-context { display: flex; gap: 8px 20px; flex-wrap: wrap; padding: 8px 16px; }
|
|
119
|
+
.twgit-connection { margin: 0 16px 8px; max-height: 45%; overflow: auto; }
|
|
120
|
+
.twgit-content { display: grid; grid-template-columns: minmax(230px, 30%) minmax(0, 1fr); flex: 1; min-height: 0; }
|
|
121
|
+
.twgit-panel aside { padding: 0 14px 14px; overflow: auto; border-right: 1px solid GrayText; }
|
|
122
|
+
.twgit-panel aside ul { list-style: none; padding: 0; margin: 4px 0; }
|
|
123
|
+
.twgit-panel aside li { overflow-wrap: anywhere; }
|
|
124
|
+
.twgit-panel summary { cursor: pointer; }
|
|
125
|
+
.twgit-panel .twgit-file { width: 100%; border: 0; margin: 1px 0; }
|
|
126
|
+
.twgit-file span { display: inline-block; width: 1.4em; font-family: monospace; }
|
|
127
|
+
.twgit-diff { padding: 0 16px 16px; min-width: 0; overflow: auto; }
|
|
128
|
+
.twgit-diff .diff { font-size: 12px; }
|
|
129
|
+
.twgit-history { list-style: none; margin: 0; padding: 0; }
|
|
130
|
+
.twgit-history li { padding: 5px 0; }
|
|
131
|
+
.twgit-history small { display: block; font-size: 11px; }
|
|
132
|
+
.twgit-panel > footer { font-size: 11px; padding: 8px 16px; border-top: 1px solid GrayText; }
|
|
133
|
+
.twgit-error { margin: 6px 16px; color: #a11919; padding: 8px; background: #fff0f0; }
|
|
134
|
+
@media (max-width: 700px) { .twgit-content { grid-template-columns: minmax(180px, 42%) minmax(0, 1fr); } .twgit-panel > header { flex-wrap: wrap; } }
|
|
135
|
+
.twgit-view-switch { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 10px; }
|
|
136
|
+
.twgit-review-unreadable { margin: 6px 0; padding: 8px; background: color-mix(in srgb, #d9822b 16%, Canvas); }
|
|
137
|
+
.twgit-review-comparison .twgit-review-overview dl { margin: 4px 0 8px; }
|
|
138
|
+
/*$vite$:1*/
|