@orz/ui-code 0.0.0-stage → 0.0.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 +29 -0
- package/README.md +216 -2
- package/dist/capped-code-block.d.ts +21 -0
- package/dist/capped-code-block.d.ts.map +1 -0
- package/dist/capped-code-block.js +41 -0
- package/dist/capped-code-block.js.map +1 -0
- package/dist/code-block.d.ts +147 -0
- package/dist/code-block.d.ts.map +1 -0
- package/dist/code-block.js +494 -0
- package/dist/code-block.js.map +1 -0
- package/dist/code-worker.d.ts +28 -0
- package/dist/code-worker.d.ts.map +1 -0
- package/dist/code-worker.js +29 -0
- package/dist/code-worker.js.map +1 -0
- package/dist/content.d.ts +12 -0
- package/dist/content.d.ts.map +1 -0
- package/dist/content.js +35 -0
- package/dist/content.js.map +1 -0
- package/dist/file-text.d.ts +16 -0
- package/dist/file-text.d.ts.map +1 -0
- package/dist/file-text.js +37 -0
- package/dist/file-text.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/patch-commit.d.ts +27 -0
- package/dist/patch-commit.d.ts.map +1 -0
- package/dist/patch-commit.js +109 -0
- package/dist/patch-commit.js.map +1 -0
- package/dist/patch-content.d.ts +13 -0
- package/dist/patch-content.d.ts.map +1 -0
- package/dist/patch-content.js +43 -0
- package/dist/patch-content.js.map +1 -0
- package/dist/patch-view.d.ts +49 -0
- package/dist/patch-view.d.ts.map +1 -0
- package/dist/patch-view.js +167 -0
- package/dist/patch-view.js.map +1 -0
- package/dist/word-diff.d.ts +82 -0
- package/dist/word-diff.d.ts.map +1 -0
- package/dist/word-diff.js +209 -0
- package/dist/word-diff.js.map +1 -0
- package/package.json +63 -3
- package/styles.css +34 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Word-like tokens of `text`, weighted by how many characters each spends.
|
|
3
|
+
* This is what `alignGroups` scores a candidate pair with (T-211): the
|
|
4
|
+
* question there is only "are these two the same block", and a bag of words
|
|
5
|
+
* answers it without the quadratic cost of a real diff — which matters once
|
|
6
|
+
* the run being scored is a whole rewritten section rather than one line
|
|
7
|
+
* hunk. Spaces and punctuation stay out: T-180 already found those to be
|
|
8
|
+
* the anchors that mean nothing.
|
|
9
|
+
*
|
|
10
|
+
* What it weighs is prose. A candidate that can also hold pictures goes
|
|
11
|
+
* through `bagWith`, which counts those by identity instead (T-239).
|
|
12
|
+
*/
|
|
13
|
+
export type WordBag = {
|
|
14
|
+
weights: Map<string, number>;
|
|
15
|
+
total: number;
|
|
16
|
+
};
|
|
17
|
+
export declare function wordBag(text: string): WordBag;
|
|
18
|
+
/** The bag of `text`, plus one entry for each of `urls`.
|
|
19
|
+
*
|
|
20
|
+
* An image used to reach the bag as its markdown source, and a word is weighed
|
|
21
|
+
* by its characters, so `/api/projects/<slug>/attachments/<id>/download/` —
|
|
22
|
+
* the path every attachment in one deployment shares — became the vocabulary
|
|
23
|
+
* two unrelated tables had most in common (T-239). Two tables sharing nothing
|
|
24
|
+
* but the fact of holding attachments scored 0.69 against each other while a
|
|
25
|
+
* table and its real counterpart scored 0.22, and both numbers get worse the
|
|
26
|
+
* longer the deployment spells that prefix.
|
|
27
|
+
*
|
|
28
|
+
* A url is an identity, not prose: worth counting that this picture is that
|
|
29
|
+
* picture, worth nothing to count how many characters the path to it spends.
|
|
30
|
+
* So each one lands as a single fixed-weight entry under a key no prose can
|
|
31
|
+
* collide with — `wordBag` keeps `isWordLike` segments only, which one
|
|
32
|
+
* non-word character in front is enough to stay clear of.
|
|
33
|
+
*/
|
|
34
|
+
export declare function bagWith(text: string, urls: string[]): WordBag;
|
|
35
|
+
/** Half-open character range `[start, end)`. */
|
|
36
|
+
export type WordDiffRange = {
|
|
37
|
+
start: number;
|
|
38
|
+
end: number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Text present in the old side and gone from the new one. `at` is where it
|
|
42
|
+
* sat in the new text (a caret, not a span — deleted text has no new-side
|
|
43
|
+
* extent); `from`/`to` locate it in the old text so the caller can quote it.
|
|
44
|
+
*/
|
|
45
|
+
export type WordDiffDeletion = {
|
|
46
|
+
at: number;
|
|
47
|
+
from: number;
|
|
48
|
+
to: number;
|
|
49
|
+
};
|
|
50
|
+
export type WordDiffResult = {
|
|
51
|
+
ins: WordDiffRange[];
|
|
52
|
+
del: WordDiffDeletion[];
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Word-level edits with the anchors that cost more than they earn folded into
|
|
56
|
+
* the change around them (T-180).
|
|
57
|
+
*
|
|
58
|
+
* A heavily rewritten line still shares spaces, punctuation and the odd single
|
|
59
|
+
* character with the line it replaced, and every one of those the word diff
|
|
60
|
+
* keeps cuts the rewrite apart: the reader is told `format.ts` became `引入`
|
|
61
|
+
* and `East` became `sindresorhus,纯`, pairings that carry no meaning, while
|
|
62
|
+
* the sentence's genuinely untouched tail drowns among the fragments. An
|
|
63
|
+
* anchor is only worth drawing around when it outweighs the change on *both*
|
|
64
|
+
* sides of it; a lighter one is folded in, and the two sides each run together
|
|
65
|
+
* into a single coherent before and after.
|
|
66
|
+
*
|
|
67
|
+
* No threshold is involved, which is the point: a small edit keeps every
|
|
68
|
+
* anchor it has and comes out word-level exactly as it did before, while a
|
|
69
|
+
* line rewritten past the last surviving anchor degrades into the whole-block
|
|
70
|
+
* before/after T-142 already renders for a pair that shares nothing. Weight is
|
|
71
|
+
* in characters and a tie leaves the anchor standing — the conservative of the
|
|
72
|
+
* two tiers T-180 weighed, and tightening it later is the one comparison
|
|
73
|
+
* below.
|
|
74
|
+
*
|
|
75
|
+
* `wordDiff` keeps its bare output beside this one: coalescing answers "what
|
|
76
|
+
* should the reader see", and anything measuring how much genuinely changed
|
|
77
|
+
* would read a folded-in anchor as change that is not there.
|
|
78
|
+
*/
|
|
79
|
+
export declare function coalescedWordDiff(oldText: string, newText: string): WordDiffResult;
|
|
80
|
+
/** Word-level edits between two texts, as offsets into each side. */
|
|
81
|
+
export declare function wordDiff(oldText: string, newText: string): WordDiffResult;
|
|
82
|
+
//# sourceMappingURL=word-diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"word-diff.d.ts","sourceRoot":"","sources":["../src/word-diff.ts"],"names":[],"mappings":"AA0BA;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,OAAO,GAAG;IAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAS7C;AAYD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAQ7D;AAED,gDAAgD;AAChD,MAAM,MAAM,aAAa,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,aAAa,EAAE,CAAC;IACrB,GAAG,EAAE,gBAAgB,EAAE,CAAC;CACzB,CAAC;AAsCF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,cAAc,CAuDhB;AAED,qEAAqE;AACrE,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CA4BzE"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { Diff } from "diff";
|
|
2
|
+
/**
|
|
3
|
+
* Word segmentation that works without spaces. jsdiff's own `diffWords`
|
|
4
|
+
* splits on whitespace, so an edited Chinese sentence is one giant token
|
|
5
|
+
* and the whole paragraph reads as changed — the exact complaint T-142
|
|
6
|
+
* exists to fix. `Intl.Segmenter` knows where words end in CJK as well as
|
|
7
|
+
* in English, and keeps whitespace and punctuation as their own segments,
|
|
8
|
+
* which is what makes "one word replaced" come out as one word replaced.
|
|
9
|
+
*/
|
|
10
|
+
const segmenter = new Intl.Segmenter(undefined, { granularity: "word" });
|
|
11
|
+
class WordDiff extends Diff {
|
|
12
|
+
tokenize(value) {
|
|
13
|
+
const tokens = [];
|
|
14
|
+
for (const { segment } of segmenter.segment(value))
|
|
15
|
+
tokens.push(segment);
|
|
16
|
+
return tokens;
|
|
17
|
+
}
|
|
18
|
+
join(tokens) {
|
|
19
|
+
return tokens.join("");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const differ = new WordDiff();
|
|
23
|
+
export function wordBag(text) {
|
|
24
|
+
const weights = new Map();
|
|
25
|
+
let total = 0;
|
|
26
|
+
for (const { segment, isWordLike } of segmenter.segment(text)) {
|
|
27
|
+
if (isWordLike !== true)
|
|
28
|
+
continue;
|
|
29
|
+
weights.set(segment, (weights.get(segment) ?? 0) + segment.length);
|
|
30
|
+
total += segment.length;
|
|
31
|
+
}
|
|
32
|
+
return { weights, total };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* What one picture is worth against one character of prose. It is a rate, not
|
|
36
|
+
* a threshold — it rules nothing out, it only gives an image enough weight to
|
|
37
|
+
* take part in the score at all. T-239 swept 1 through 20 and every fixture
|
|
38
|
+
* came out identical; at 40 one picture outweighs all the prose beside it and
|
|
39
|
+
* a table that lost an image stops resembling its own counterpart, so the
|
|
40
|
+
* bottom of the flat range is what this takes.
|
|
41
|
+
*/
|
|
42
|
+
const IMAGE_WEIGHT = 1;
|
|
43
|
+
/** The bag of `text`, plus one entry for each of `urls`.
|
|
44
|
+
*
|
|
45
|
+
* An image used to reach the bag as its markdown source, and a word is weighed
|
|
46
|
+
* by its characters, so `/api/projects/<slug>/attachments/<id>/download/` —
|
|
47
|
+
* the path every attachment in one deployment shares — became the vocabulary
|
|
48
|
+
* two unrelated tables had most in common (T-239). Two tables sharing nothing
|
|
49
|
+
* but the fact of holding attachments scored 0.69 against each other while a
|
|
50
|
+
* table and its real counterpart scored 0.22, and both numbers get worse the
|
|
51
|
+
* longer the deployment spells that prefix.
|
|
52
|
+
*
|
|
53
|
+
* A url is an identity, not prose: worth counting that this picture is that
|
|
54
|
+
* picture, worth nothing to count how many characters the path to it spends.
|
|
55
|
+
* So each one lands as a single fixed-weight entry under a key no prose can
|
|
56
|
+
* collide with — `wordBag` keeps `isWordLike` segments only, which one
|
|
57
|
+
* non-word character in front is enough to stay clear of.
|
|
58
|
+
*/
|
|
59
|
+
export function bagWith(text, urls) {
|
|
60
|
+
const bag = wordBag(text);
|
|
61
|
+
for (const url of urls) {
|
|
62
|
+
const key = `\u0000${url}`;
|
|
63
|
+
bag.weights.set(key, (bag.weights.get(key) ?? 0) + IMAGE_WEIGHT);
|
|
64
|
+
bag.total += IMAGE_WEIGHT;
|
|
65
|
+
}
|
|
66
|
+
return bag;
|
|
67
|
+
}
|
|
68
|
+
function diffRuns(oldText, newText) {
|
|
69
|
+
const runs = [];
|
|
70
|
+
let edit = null;
|
|
71
|
+
for (const part of differ.diff(oldText, newText)) {
|
|
72
|
+
if (part.added || part.removed) {
|
|
73
|
+
if (edit === null) {
|
|
74
|
+
edit = { kind: "edit", del: "", ins: "" };
|
|
75
|
+
runs.push(edit);
|
|
76
|
+
}
|
|
77
|
+
if (part.added)
|
|
78
|
+
edit.ins += part.value;
|
|
79
|
+
else
|
|
80
|
+
edit.del += part.value;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
edit = null;
|
|
84
|
+
const last = runs.at(-1);
|
|
85
|
+
if (last !== undefined && last.kind === "eq")
|
|
86
|
+
last.text += part.value;
|
|
87
|
+
else
|
|
88
|
+
runs.push({ kind: "eq", text: part.value });
|
|
89
|
+
}
|
|
90
|
+
return runs;
|
|
91
|
+
}
|
|
92
|
+
/** How much a run of changed text weighs against a neighbouring anchor. */
|
|
93
|
+
function weightOf(run) {
|
|
94
|
+
return Math.max(run.del.length, run.ins.length);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Word-level edits with the anchors that cost more than they earn folded into
|
|
98
|
+
* the change around them (T-180).
|
|
99
|
+
*
|
|
100
|
+
* A heavily rewritten line still shares spaces, punctuation and the odd single
|
|
101
|
+
* character with the line it replaced, and every one of those the word diff
|
|
102
|
+
* keeps cuts the rewrite apart: the reader is told `format.ts` became `引入`
|
|
103
|
+
* and `East` became `sindresorhus,纯`, pairings that carry no meaning, while
|
|
104
|
+
* the sentence's genuinely untouched tail drowns among the fragments. An
|
|
105
|
+
* anchor is only worth drawing around when it outweighs the change on *both*
|
|
106
|
+
* sides of it; a lighter one is folded in, and the two sides each run together
|
|
107
|
+
* into a single coherent before and after.
|
|
108
|
+
*
|
|
109
|
+
* No threshold is involved, which is the point: a small edit keeps every
|
|
110
|
+
* anchor it has and comes out word-level exactly as it did before, while a
|
|
111
|
+
* line rewritten past the last surviving anchor degrades into the whole-block
|
|
112
|
+
* before/after T-142 already renders for a pair that shares nothing. Weight is
|
|
113
|
+
* in characters and a tie leaves the anchor standing — the conservative of the
|
|
114
|
+
* two tiers T-180 weighed, and tightening it later is the one comparison
|
|
115
|
+
* below.
|
|
116
|
+
*
|
|
117
|
+
* `wordDiff` keeps its bare output beside this one: coalescing answers "what
|
|
118
|
+
* should the reader see", and anything measuring how much genuinely changed
|
|
119
|
+
* would read a folded-in anchor as change that is not there.
|
|
120
|
+
*/
|
|
121
|
+
export function coalescedWordDiff(oldText, newText) {
|
|
122
|
+
if (oldText === newText)
|
|
123
|
+
return { ins: [], del: [] };
|
|
124
|
+
const runs = diffRuns(oldText, newText);
|
|
125
|
+
// The first and last run are never anchors with a change on either side, so
|
|
126
|
+
// the text a line opens and closes with survives however heavy the rewrite
|
|
127
|
+
// between them — which is how the evidence line keeps its untouched tail.
|
|
128
|
+
for (let i = 1; i + 1 < runs.length;) {
|
|
129
|
+
const anchor = runs[i];
|
|
130
|
+
const before = runs[i - 1];
|
|
131
|
+
const after = runs[i + 1];
|
|
132
|
+
if (anchor?.kind !== "eq" ||
|
|
133
|
+
before?.kind !== "edit" ||
|
|
134
|
+
after?.kind !== "edit" ||
|
|
135
|
+
anchor.text.length >= weightOf(before) ||
|
|
136
|
+
anchor.text.length >= weightOf(after)) {
|
|
137
|
+
i++;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
runs.splice(i - 1, 3, {
|
|
141
|
+
kind: "edit",
|
|
142
|
+
del: before.del + anchor.text + after.del,
|
|
143
|
+
ins: before.ins + anchor.text + after.ins,
|
|
144
|
+
});
|
|
145
|
+
// Leaving `i` where it is lands on the anchor after the merged run, which
|
|
146
|
+
// now weighs itself against the heavier thing folding produced — that is
|
|
147
|
+
// how a run of light anchors collapses together in one pass. An anchor
|
|
148
|
+
// already found heavy enough is never revisited: letting a growing
|
|
149
|
+
// neighbour come back for it would erode surviving anchors one at a time
|
|
150
|
+
// until only the first and last stood, which is the aggressive tier T-180
|
|
151
|
+
// ruled against.
|
|
152
|
+
}
|
|
153
|
+
const ins = [];
|
|
154
|
+
const del = [];
|
|
155
|
+
let oldPos = 0;
|
|
156
|
+
let newPos = 0;
|
|
157
|
+
for (const run of runs) {
|
|
158
|
+
if (run.kind === "eq") {
|
|
159
|
+
oldPos += run.text.length;
|
|
160
|
+
newPos += run.text.length;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (run.del !== "") {
|
|
164
|
+
del.push({ at: newPos, from: oldPos, to: oldPos + run.del.length });
|
|
165
|
+
oldPos += run.del.length;
|
|
166
|
+
}
|
|
167
|
+
if (run.ins !== "") {
|
|
168
|
+
ins.push({ start: newPos, end: newPos + run.ins.length });
|
|
169
|
+
newPos += run.ins.length;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return { ins, del };
|
|
173
|
+
}
|
|
174
|
+
/** Word-level edits between two texts, as offsets into each side. */
|
|
175
|
+
export function wordDiff(oldText, newText) {
|
|
176
|
+
const ins = [];
|
|
177
|
+
const del = [];
|
|
178
|
+
if (oldText === newText)
|
|
179
|
+
return { ins, del };
|
|
180
|
+
let oldPos = 0;
|
|
181
|
+
let newPos = 0;
|
|
182
|
+
for (const part of differ.diff(oldText, newText)) {
|
|
183
|
+
const length = part.value.length;
|
|
184
|
+
if (part.added) {
|
|
185
|
+
const last = ins.at(-1);
|
|
186
|
+
if (last !== undefined && last.end === newPos)
|
|
187
|
+
last.end = newPos + length;
|
|
188
|
+
else
|
|
189
|
+
ins.push({ start: newPos, end: newPos + length });
|
|
190
|
+
newPos += length;
|
|
191
|
+
}
|
|
192
|
+
else if (part.removed) {
|
|
193
|
+
const last = del.at(-1);
|
|
194
|
+
if (last !== undefined && last.at === newPos && last.to === oldPos) {
|
|
195
|
+
last.to = oldPos + length;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
del.push({ at: newPos, from: oldPos, to: oldPos + length });
|
|
199
|
+
}
|
|
200
|
+
oldPos += length;
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
oldPos += length;
|
|
204
|
+
newPos += length;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return { ins, del };
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=word-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"word-diff.js","sourceRoot":"","sources":["../src/word-diff.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,66 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orz/ui-code",
|
|
3
|
-
"version": "0.0.0
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Syntax-highlighted code and diff blocks on pierre, a CJK-aware word differ, and the code renderer for the @orz/ui-content registry",
|
|
5
|
+
"license": "BSD-3-Clause",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/orzFly/ui.git",
|
|
9
|
+
"directory": "packages/ui-code"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"sideEffects": [
|
|
13
|
+
"**/*.css"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"@orz/source": "./src/index.ts",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./word-diff": {
|
|
22
|
+
"@orz/source": "./src/word-diff.ts",
|
|
23
|
+
"types": "./dist/word-diff.d.ts",
|
|
24
|
+
"default": "./dist/word-diff.js"
|
|
25
|
+
},
|
|
26
|
+
"./styles.css": "./styles.css"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"styles.css"
|
|
31
|
+
],
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@pierre/diffs": "^1.6.1",
|
|
37
|
+
"lucide-react": "^1",
|
|
38
|
+
"react": "^19",
|
|
39
|
+
"react-dom": "^19",
|
|
40
|
+
"@orz/ui": "^0.0.0",
|
|
41
|
+
"@orz/ui-content": "^0.0.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"diff": "^9.0.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@pierre/diffs": "^1.6.1",
|
|
48
|
+
"@testing-library/react": "^16.3.2",
|
|
49
|
+
"@types/node": "^22.20.5",
|
|
50
|
+
"@types/react": "^19.2.18",
|
|
51
|
+
"@types/react-dom": "^19.2.4",
|
|
52
|
+
"happy-dom": "^21.0.3",
|
|
53
|
+
"lucide-react": "^1.31.0",
|
|
54
|
+
"react": "^19.2.8",
|
|
55
|
+
"react-dom": "^19.2.8",
|
|
56
|
+
"vitest": "^5.0.5",
|
|
57
|
+
"@orz/themes": "0.0.0",
|
|
58
|
+
"@orz/ui": "0.0.0",
|
|
59
|
+
"@orz/ui-content": "0.0.0"
|
|
60
|
+
},
|
|
61
|
+
"scripts": {
|
|
62
|
+
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json",
|
|
63
|
+
"typecheck": "tsc --noEmit",
|
|
64
|
+
"test": "vitest run"
|
|
65
|
+
}
|
|
6
66
|
}
|
package/styles.css
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* Tailwind resolves an imported file's @source against that file, so a
|
|
2
|
+
consumer importing this stylesheet scans the classes in the package's
|
|
3
|
+
shipped JS without writing an @source of its own. */
|
|
4
|
+
@source "./dist";
|
|
5
|
+
|
|
6
|
+
/* Every pierre code surface renders in a shadow root and resolves its
|
|
7
|
+
palette with light-dark(); declarations from the outer tree win over
|
|
8
|
+
shadow :host rules, which is what lets these lines keep pierre in step
|
|
9
|
+
with the app theme.
|
|
10
|
+
|
|
11
|
+
The bg/fg pairs override what the syntax theme wrote into :host, and every
|
|
12
|
+
other chrome color pierre uses — line-number gutter, context rows, hunk
|
|
13
|
+
separators, the addition/deletion tints — is color-mix()'d off them, so
|
|
14
|
+
aligning these four aligns the whole surface, including themes with no
|
|
15
|
+
syntax counterpart to map to (T-144). */
|
|
16
|
+
diffs-container {
|
|
17
|
+
color-scheme: light;
|
|
18
|
+
--diffs-light-bg: var(--background);
|
|
19
|
+
--diffs-dark-bg: var(--background);
|
|
20
|
+
--diffs-light: var(--foreground);
|
|
21
|
+
--diffs-dark: var(--foreground);
|
|
22
|
+
}
|
|
23
|
+
.dark diffs-container {
|
|
24
|
+
color-scheme: dark;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* A patch's +/- counts take the theme's diff colours, mixed toward the
|
|
28
|
+
foreground so small text stays legible. */
|
|
29
|
+
.diff-addition-text {
|
|
30
|
+
color: color-mix(in oklab, var(--foreground) 75%, var(--diff-addition));
|
|
31
|
+
}
|
|
32
|
+
.diff-deletion-text {
|
|
33
|
+
color: color-mix(in oklab, var(--foreground) 75%, var(--diff-deletion));
|
|
34
|
+
}
|