mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-23 07:10:41 +00:00
Fix #519 by manually creating the patch when github doesn't give it
This commit is contained in:
27
package-lock.json
generated
27
package-lock.json
generated
@@ -34,6 +34,7 @@
|
||||
"deepslate-1.18": "npm:deepslate@0.9.0-beta.9",
|
||||
"deepslate-1.18.2": "npm:deepslate@0.9.0",
|
||||
"deepslate-1.20.4": "npm:deepslate@0.20.1",
|
||||
"diff": "^7.0.0",
|
||||
"highlight.js": "^11.5.1",
|
||||
"howler": "^2.2.3",
|
||||
"js-yaml": "^3.14.1",
|
||||
@@ -45,6 +46,7 @@
|
||||
"devDependencies": {
|
||||
"@preact/preset-vite": "^2.4.0",
|
||||
"@rollup/plugin-html": "^1.0.1",
|
||||
"@types/diff": "^5.2.2",
|
||||
"@types/google.analytics": "0.0.40",
|
||||
"@types/gtag.js": "^0.0.10",
|
||||
"@types/howler": "^2.2.4",
|
||||
@@ -872,6 +874,12 @@
|
||||
"node": ">= 8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/diff": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.2.tgz",
|
||||
"integrity": "sha512-qVqLpd49rmJA2nZzLVsmfS/aiiBpfVE95dHhPVwG0NmSBAt+riPxnj53wq2oBq5m4Q2RF1IWFEUpnZTgrQZfEQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/google.analytics": {
|
||||
"version": "0.0.40",
|
||||
"resolved": "https://registry.npmjs.org/@types/google.analytics/-/google.analytics-0.0.40.tgz",
|
||||
@@ -1687,6 +1695,14 @@
|
||||
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz",
|
||||
"integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/dir-glob": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||
@@ -4972,6 +4988,12 @@
|
||||
"picomatch": "^2.2.2"
|
||||
}
|
||||
},
|
||||
"@types/diff": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.2.tgz",
|
||||
"integrity": "sha512-qVqLpd49rmJA2nZzLVsmfS/aiiBpfVE95dHhPVwG0NmSBAt+riPxnj53wq2oBq5m4Q2RF1IWFEUpnZTgrQZfEQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/google.analytics": {
|
||||
"version": "0.0.40",
|
||||
"resolved": "https://registry.npmjs.org/@types/google.analytics/-/google.analytics-0.0.40.tgz",
|
||||
@@ -5516,6 +5538,11 @@
|
||||
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
|
||||
"dev": true
|
||||
},
|
||||
"diff": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz",
|
||||
"integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw=="
|
||||
},
|
||||
"dir-glob": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"deepslate-1.18.2": "npm:deepslate@0.9.0",
|
||||
"deepslate-1.20.4": "npm:deepslate@0.20.1",
|
||||
"deepslate": "^0.22.3",
|
||||
"diff": "^7.0.0",
|
||||
"highlight.js": "^11.5.1",
|
||||
"howler": "^2.2.3",
|
||||
"js-yaml": "^3.14.1",
|
||||
@@ -51,6 +52,7 @@
|
||||
"devDependencies": {
|
||||
"@preact/preset-vite": "^2.4.0",
|
||||
"@rollup/plugin-html": "^1.0.1",
|
||||
"@types/diff": "^5.2.2",
|
||||
"@types/google.analytics": "0.0.40",
|
||||
"@types/gtag.js": "^0.0.10",
|
||||
"@types/howler": "^2.2.4",
|
||||
|
||||
@@ -562,6 +562,11 @@ export function parseGitPatch(patch: string) {
|
||||
let after = 1
|
||||
for (let i = 0; i < source.length; i += 1) {
|
||||
const line = source[i]
|
||||
if (line.startsWith('Index: ') || line.startsWith('===')
|
||||
|| line.startsWith('---') || line.startsWith('+++')
|
||||
|| line.startsWith('\\') || line.length === 0) {
|
||||
continue
|
||||
}
|
||||
if (line.startsWith('@')) {
|
||||
const match = line.match(/^@@ -(\d+)(?:,(?:\d+))? \+(\d+)(?:,(?:\d+))? @@/)
|
||||
if (!match) throw new Error(`Invalid patch pattern at line ${i+1}: ${line}`)
|
||||
@@ -578,8 +583,8 @@ export function parseGitPatch(patch: string) {
|
||||
} else if (line.startsWith('-')) {
|
||||
result.push({ line, before })
|
||||
before += 1
|
||||
} else if (!line.startsWith('\\')) {
|
||||
throw new Error(`Invalid patch, got ${line.charAt(0)} at line ${i+1}`)
|
||||
} else {
|
||||
throw new Error(`Invalid patch, got '${line.charAt(0)}' at line ${i+1}`)
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { useCallback, useEffect, useMemo, useRef } from "preact/hooks"
|
||||
import { parseGitPatch } from "../../Utils.js"
|
||||
import { useLocale } from "../../contexts/Locale.jsx"
|
||||
import { useAsync } from "../../hooks/useAsync.js"
|
||||
import { useLocalStorage } from "../../hooks/useLocalStorage.js"
|
||||
import { useSearchParam } from "../../hooks/useSearchParam.js"
|
||||
import { GitHubCommitFile, fetchVersionDiff } from "../../services/DataFetcher.js"
|
||||
import { ErrorPanel } from "../ErrorPanel.jsx"
|
||||
import { Octicon } from "../Octicon.jsx"
|
||||
import { TreeView, TreeViewGroupRenderer, TreeViewLeafRenderer } from "../TreeView.jsx"
|
||||
import { createPatch } from 'diff'
|
||||
import { useCallback, useEffect, useRef } from 'preact/hooks'
|
||||
import { useLocale } from '../../contexts/Locale.jsx'
|
||||
import { useAsync } from '../../hooks/useAsync.js'
|
||||
import { useLocalStorage } from '../../hooks/useLocalStorage.js'
|
||||
import { useSearchParam } from '../../hooks/useSearchParam.js'
|
||||
import type { GitHubCommitFile } from '../../services/DataFetcher.js'
|
||||
import { fetchVersionDiff } from '../../services/DataFetcher.js'
|
||||
import { parseGitPatch } from '../../Utils.js'
|
||||
import { ErrorPanel } from '../ErrorPanel.jsx'
|
||||
import { Octicon } from '../Octicon.jsx'
|
||||
import type { TreeViewGroupRenderer, TreeViewLeafRenderer } from '../TreeView.jsx'
|
||||
import { TreeView } from '../TreeView.jsx'
|
||||
|
||||
const mcmetaRawUrl = 'https://raw.githubusercontent.com/misode/mcmeta'
|
||||
const mcmetaBlobUrl = 'https://github.com/misode/mcmeta/blob'
|
||||
@@ -30,35 +33,45 @@ export function VersionDiff({ version }: Props) {
|
||||
}
|
||||
}, [diffView, setFilename])
|
||||
|
||||
const { file, diff } = useMemo(() => {
|
||||
const { value, loading } = useAsync(async () => {
|
||||
if (filename === undefined) return { file: undefined, diff: undefined }
|
||||
const file = commit?.files.find(f => f.filename === filename)
|
||||
if (file === undefined) return { file, diff: undefined }
|
||||
if (file.patch === undefined) {
|
||||
const match = filename.match(/\.(png|ogg)$/)
|
||||
if (match) {
|
||||
let patch = file.patch
|
||||
if (patch === undefined) {
|
||||
const isMedia = filename.match(/\.(png|ogg)$/)
|
||||
const isText = filename.match(/\.(txt|json|mcmeta)$/)
|
||||
if (isMedia) {
|
||||
return {
|
||||
file,
|
||||
diff: {
|
||||
type: match[1],
|
||||
type: isMedia[1],
|
||||
before: file.status === 'added' ? undefined : `${mcmetaRawUrl}/${commit?.parents[0].sha}/${filename}`,
|
||||
after: file.status === 'removed' ? undefined : `${mcmetaRawUrl}/${version}-diff/${filename}`,
|
||||
},
|
||||
}
|
||||
} else if (file.status === 'renamed') {
|
||||
return { file, diff: [] }
|
||||
} else {
|
||||
return { file, diff: new Error('Cannot display diff for this file') }
|
||||
} else if (isText) {
|
||||
const [beforeStr, afterStr] = await Promise.all([
|
||||
fetch(`${mcmetaRawUrl}/${commit?.parents[0].sha}/${filename}`).then(r => r.text()),
|
||||
fetch(`${mcmetaRawUrl}/${version}-diff/${filename}`).then(r => r.text()),
|
||||
])
|
||||
patch = createPatch(filename, beforeStr, afterStr)
|
||||
}
|
||||
}
|
||||
if (patch === undefined) {
|
||||
return { file, diff: new Error('Cannot display diff for this file') }
|
||||
}
|
||||
try {
|
||||
return { file, diff: parseGitPatch(file.patch) }
|
||||
return { file, diff: parseGitPatch(patch) }
|
||||
} catch (e) {
|
||||
const error = e as Error
|
||||
error.message = `Failed to show diff: ${error.message}`
|
||||
return { file, diff: error }
|
||||
}
|
||||
}, [filename, commit])
|
||||
const { file, diff } = value ?? {}
|
||||
|
||||
const DiffFolder: TreeViewGroupRenderer = useCallback(({ name, open, onClick }) => {
|
||||
return <div class="diff-entry select-none" onClick={onClick} >
|
||||
@@ -71,7 +84,7 @@ export function VersionDiff({ version }: Props) {
|
||||
return <div class={`diff-entry py-0.5 flex items-center [&>svg]:shrink-0 select-none ${entry.filename === filename ? 'active' : ''}`} onClick={() => selectFile(entry.filename)} title={entry.filename}>
|
||||
<span class="ml-[15px] mx-2 overflow-hidden text-ellipsis whitespace-nowrap">{entry.filename.split('/').at(-1)}</span>
|
||||
<span class={`ml-auto diff-${entry.status}`}>{Octicon[`diff_${entry.status}`]}</span>
|
||||
</div>
|
||||
</div>
|
||||
}, [filename])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -106,12 +119,12 @@ export function VersionDiff({ version }: Props) {
|
||||
<div class={`diff-tree w-full md:w-64 md:overflow-y-scroll md:overscroll-contain md:sticky md:top-[56px] ${filename ? 'hidden md:block' : 'block'}`}>
|
||||
<TreeView entries={commit?.files ?? []} group={DiffFolder} leaf={DiffEntry} split={file => file.filename.split('/')} />
|
||||
</div>
|
||||
{filename && <div key={filename} class={`diff-view-panel flex-1 min-w-0 md:pl-2 md:ml-64`}>
|
||||
{filename && <div key={filename} class={'diff-view-panel flex-1 min-w-0 md:pl-2 md:ml-64'}>
|
||||
<div class="flex justify-center items-center min-w-0 text-center py-2" title={filename}>
|
||||
<span class="mr-2 min-w-0 overflow-hidden text-ellipsis font-bold text-xl">{filename}</span>
|
||||
<a class="diff-toggle p-1" href={`${mcmetaBlobUrl}/${version}-diff/${filename}`} target="_blank">{Octicon.link_external}</a>
|
||||
</div>
|
||||
{diff === undefined ? (
|
||||
{(diff === undefined || loading) ? (
|
||||
<span class="note">{locale('loading')}</span>
|
||||
) : diff instanceof Error ? (
|
||||
<ErrorPanel error={diff} />
|
||||
@@ -134,7 +147,7 @@ export function VersionDiff({ version }: Props) {
|
||||
)}
|
||||
</div>
|
||||
) : <>
|
||||
{file.previous_filename !== undefined && <div class="flex justify-center font-mono flex-wrap" title={`${file.previous_filename} → ${filename}`}>
|
||||
{file?.previous_filename !== undefined && <div class="flex justify-center font-mono flex-wrap" title={`${file.previous_filename} → ${filename}`}>
|
||||
<span class="overflow-hidden text-ellipsis mr-2">{file.previous_filename}</span>
|
||||
<span class="overflow-hidden text-ellipsis whitespace-nowrap"><span class="select-none">→ </span>{filename}</span>
|
||||
</div>}
|
||||
|
||||
Reference in New Issue
Block a user