mirror of
https://github.com/sst/opencode.git
synced 2025-08-31 02:07:24 +00:00
docs: share page responsive diff
This commit is contained in:
parent
ab23167f80
commit
008af18156
3 changed files with 139 additions and 87 deletions
|
@ -54,8 +54,8 @@ const DiffView: Component<DiffViewProps> = (props) => {
|
||||||
// Pair removals with additions
|
// Pair removals with additions
|
||||||
const maxLength = Math.max(removals.length, additions.length)
|
const maxLength = Math.max(removals.length, additions.length)
|
||||||
for (let k = 0; k < maxLength; k++) {
|
for (let k = 0; k < maxLength; k++) {
|
||||||
const hasLeft = !!removals[k]
|
const hasLeft = k < removals.length
|
||||||
const hasRight = !!additions[k]
|
const hasRight = k < additions.length
|
||||||
|
|
||||||
if (hasLeft && hasRight) {
|
if (hasLeft && hasRight) {
|
||||||
// Replacement - left is removed, right is added
|
// Replacement - left is removed, right is added
|
||||||
|
@ -71,8 +71,8 @@ const DiffView: Component<DiffViewProps> = (props) => {
|
||||||
right: "",
|
right: "",
|
||||||
type: "removed"
|
type: "removed"
|
||||||
})
|
})
|
||||||
} else {
|
} else if (hasRight) {
|
||||||
// Pure addition
|
// Pure addition - only create if we actually have content
|
||||||
diffRows.push({
|
diffRows.push({
|
||||||
left: "",
|
left: "",
|
||||||
right: additions[k],
|
right: additions[k],
|
||||||
|
@ -111,85 +111,136 @@ const DiffView: Component<DiffViewProps> = (props) => {
|
||||||
return diffRows
|
return diffRows
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const mobileRows = createMemo(() => {
|
||||||
|
const mobileBlocks: { type: 'removed' | 'added' | 'unchanged', lines: string[] }[] = []
|
||||||
|
const currentRows = rows()
|
||||||
|
|
||||||
|
let i = 0
|
||||||
|
while (i < currentRows.length) {
|
||||||
|
const removedLines: string[] = []
|
||||||
|
const addedLines: string[] = []
|
||||||
|
|
||||||
|
// Collect consecutive modified/removed/added rows
|
||||||
|
while (i < currentRows.length &&
|
||||||
|
(currentRows[i].type === 'modified' ||
|
||||||
|
currentRows[i].type === 'removed' ||
|
||||||
|
currentRows[i].type === 'added')) {
|
||||||
|
const row = currentRows[i]
|
||||||
|
if (row.left && (row.type === 'removed' || row.type === 'modified')) {
|
||||||
|
removedLines.push(row.left)
|
||||||
|
}
|
||||||
|
if (row.right && (row.type === 'added' || row.type === 'modified')) {
|
||||||
|
addedLines.push(row.right)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add grouped blocks
|
||||||
|
if (removedLines.length > 0) {
|
||||||
|
mobileBlocks.push({ type: 'removed', lines: removedLines })
|
||||||
|
}
|
||||||
|
if (addedLines.length > 0) {
|
||||||
|
mobileBlocks.push({ type: 'added', lines: addedLines })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add unchanged rows as-is
|
||||||
|
if (i < currentRows.length && currentRows[i].type === 'unchanged') {
|
||||||
|
mobileBlocks.push({
|
||||||
|
type: 'unchanged',
|
||||||
|
lines: [currentRows[i].left]
|
||||||
|
})
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mobileBlocks
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={`${styles.diff} ${props.class ?? ""}`}>
|
<div class={`${styles.diff} ${props.class ?? ""}`}>
|
||||||
{rows().map((r) => (
|
<div class={styles.desktopView}>
|
||||||
<div class={styles.row}>
|
{rows().map((r) => (
|
||||||
<div class={styles.beforeColumn}>
|
<div class={styles.row}>
|
||||||
<CodeBlock
|
<div class={styles.beforeColumn}>
|
||||||
code={r.left}
|
<CodeBlock
|
||||||
lang={props.lang}
|
code={r.left}
|
||||||
data-section="cell"
|
lang={props.lang}
|
||||||
data-diff-type={r.type === "removed" || r.type === "modified" ? "removed" : ""}
|
data-section="cell"
|
||||||
data-display-mobile={r.type === "added" && !r.left ? "false" : undefined}
|
data-diff-type={r.type === "removed" || r.type === "modified" ? "removed" : ""}
|
||||||
/>
|
/>
|
||||||
{(r.type === "added" || r.type === "modified") && r.right !== undefined && (
|
</div>
|
||||||
|
<div class={styles.afterColumn}>
|
||||||
<CodeBlock
|
<CodeBlock
|
||||||
code={r.right}
|
code={r.right}
|
||||||
lang={props.lang}
|
lang={props.lang}
|
||||||
data-section="cell"
|
data-section="cell"
|
||||||
data-diff-type="added"
|
data-diff-type={r.type === "added" || r.type === "modified" ? "added" : ""}
|
||||||
data-display-mobile="true"
|
|
||||||
/>
|
/>
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class={styles.afterColumn}>
|
<div class={styles.mobileView}>
|
||||||
<CodeBlock
|
{mobileRows().map((block) => (
|
||||||
code={r.right}
|
<div class={styles.mobileBlock}>
|
||||||
lang={props.lang}
|
{block.lines.map((line) => (
|
||||||
data-section="cell"
|
<CodeBlock
|
||||||
data-diff-type={r.type === "added" || r.type === "modified" ? "added" : ""}
|
code={line}
|
||||||
/>
|
lang={props.lang}
|
||||||
|
data-section="cell"
|
||||||
|
data-diff-type={block.type === 'removed' ? 'removed' :
|
||||||
|
block.type === 'added' ? 'added' : ''}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DiffView
|
export default DiffView
|
||||||
|
|
||||||
// String to test diff viewer with
|
// const testDiff = `--- combined_before.txt 2025-06-24 16:38:08
|
||||||
const testDiff = `--- combined_before.txt 2025-06-24 16:38:08
|
// +++ combined_after.txt 2025-06-24 16:38:12
|
||||||
+++ combined_after.txt 2025-06-24 16:38:12
|
// @@ -1,21 +1,25 @@
|
||||||
@@ -1,21 +1,25 @@
|
// unchanged line
|
||||||
unchanged line
|
// -deleted line
|
||||||
-deleted line
|
// -old content
|
||||||
-old content
|
// +added line
|
||||||
+added line
|
// +new content
|
||||||
+new content
|
//
|
||||||
|
// -removed empty line below
|
||||||
-removed empty line below
|
// +added empty line above
|
||||||
+added empty line above
|
//
|
||||||
|
// - tab indented
|
||||||
- tab indented
|
// -trailing spaces
|
||||||
-trailing spaces
|
// -very long line that will definitely wrap in most editors and cause potential alignment issues when displayed in a two column diff view
|
||||||
-very long line that will definitely wrap in most editors and cause potential alignment issues when displayed in a two column diff view
|
// -unicode content: 🚀 ✨ 中文
|
||||||
-unicode content: 🚀 ✨ 中文
|
// -mixed content with tabs and spaces
|
||||||
-mixed content with tabs and spaces
|
// + space indented
|
||||||
+ space indented
|
// +no trailing spaces
|
||||||
+no trailing spaces
|
// +short line
|
||||||
+short line
|
// +very long replacement line that will also wrap and test how the diff viewer handles long line additions after short line removals
|
||||||
+very long replacement line that will also wrap and test how the diff viewer handles long line additions after short line removals
|
// +different unicode: 🎉 💻 日本語
|
||||||
+different unicode: 🎉 💻 日本語
|
// +normalized content with consistent spacing
|
||||||
+normalized content with consistent spacing
|
// +newline to content
|
||||||
+newline to content
|
//
|
||||||
|
// -content to remove
|
||||||
-content to remove
|
// -whitespace only:
|
||||||
-whitespace only:
|
// -multiple
|
||||||
-multiple
|
// -consecutive
|
||||||
-consecutive
|
// -deletions
|
||||||
-deletions
|
// -single deletion
|
||||||
-single deletion
|
// +
|
||||||
+
|
// +single addition
|
||||||
+single addition
|
// +first addition
|
||||||
+first addition
|
// +second addition
|
||||||
+second addition
|
// +third addition
|
||||||
+third addition
|
// line before addition
|
||||||
line before addition
|
// +first added line
|
||||||
+first added line
|
// +
|
||||||
+
|
// +third added line
|
||||||
+third added line
|
// line after addition
|
||||||
line after addition
|
// final unchanged line`
|
||||||
final unchanged line`
|
|
||||||
|
|
|
@ -6,6 +6,19 @@
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.desktopView {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileView {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileBlock {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
|
@ -98,25 +111,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 40rem) {
|
@media (max-width: 40rem) {
|
||||||
.row {
|
.desktopView {
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.afterColumn {
|
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.beforeColumn {
|
.mobileView {
|
||||||
border-right: none;
|
display: block;
|
||||||
}
|
|
||||||
|
|
||||||
[data-section="cell"] {
|
|
||||||
&[data-display-mobile="true"] {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
&[data-display-mobile="false"] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
h4,
|
h4,
|
||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue