Skip to content

Commit

Permalink
Hex & JSON view (#14)
Browse files Browse the repository at this point in the history
* Add hex view
* Fix JSON
  • Loading branch information
Lotes committed Apr 15, 2023
1 parent 6fae73c commit 14ddf84
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 18 deletions.
2 changes: 1 addition & 1 deletion gh-pages/src/components/Breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function Breadcrumb({ filePath }: BreadcrumbProps) {
<li key={index} className="inline-flex items-center">
<span className="inline-flex items-center text-sm font-medium text-gray-700 dark:text-gray-400 dark:hover:text-white">
{index === 0 && <svg aria-hidden="true" className="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"></path></svg>}
{index !== 0 && <svg aria-hidden="true" className="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>}
{index !== 0 && <svg aria-hidden="true" className="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fillRule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clipRule="evenodd"></path></svg>}
<a href={'#'+link}>{p}</a>
</span>
</li>
Expand Down
27 changes: 27 additions & 0 deletions gh-pages/src/components/ChunkJsonViewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { asJson, KeynoteArchives, splitObjectsAs } from "keynote-archives";
import { useEffect, useState } from "react";

export interface ChunkJsonViewerProps {
data: Uint8Array;
}

export function ChunkJsonViewer({data}: ChunkJsonViewerProps) {
const [list, setList] = useState<string[]>(() => []);

useEffect(() => {
(async function() {
try{
for await (const obj of splitObjectsAs(data, KeynoteArchives)) {
const jsons = obj.messages.map(v => asJson(v.data));
setList(previous => [...previous, ...jsons]);
}
} catch(e) {
setList(['Error:'+(e as any['message'])]);
}
})();
}, []);

return <div>
{list.map((v, i) => <pre key={i} className="font-mono text-xs">{v}</pre>)}
</div>;
}
100 changes: 100 additions & 0 deletions gh-pages/src/components/HexViewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import clsx from "clsx";
import { padStart } from "lodash";
import { useMemo } from "react";

export interface HexRegion {
startAddress: number;
length: number;
color: string;
}

export interface HexViewerProps {
startAddress: number;
data: Uint8Array;
regions: HexRegion[];
}

export interface HexRowProps {
address: number;
data: number[];
from: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
to: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
}

export function HexRow({ address, data, from, to }: HexRowProps) {
if(data.length !== 8) {
data = [...data, ...new Array(8 - data.length).fill(0)];
}
return (
<div className="flex flex-row">
<span className="font-mono text-xs">
0x{address.toString(16).padStart(6, "0")}&nbsp;
</span>
{data.map((d, index) => {
return (
<span
key={index}
className={clsx("font-mono text-xs block w-fit", {
"opacity-0": index < from || index > to,
})}
>
{d.toString(16).padStart(2, "0")}
&nbsp;
</span>
);
})}
{data.map((d, index) => {
return (
<span
key={index}
className={clsx("font-mono text-xs block w-fit", {
"opacity-0": index < from || index > to,
})}
>
{d < 32 || d > 126 ? "." : String.fromCharCode(d)}
</span>
);
})}
</div>
);
}

export function HexViewer({ startAddress, data }: HexViewerProps) {
//Address (2+6, 0x123456) | Hex (8x2) | ASCII (8)
const rows = useMemo<HexRowProps[]>(() => {
const rows: HexRowProps[] = [];
const mod = startAddress % 8;
let address = startAddress - mod;
if (mod > 0) {
const rowData = new Array<number>(8).fill(0);
for (let i = mod; i < 8; i++) {
rowData[i] = data[i - mod];
}
rows.push({
address,
data: rowData,
from: mod as any,
to: 7,
});
address += 8;
}
for (let i = 0; i < data.length; i += 8) {
const slice = [...data.slice(i + mod, i + 8)];
rows.push({
address,
data: slice,
from: 0,
to: (slice.length-1) as any,
});
address += 8;
}
return rows;
}, [startAddress, data]);
return (
<div className="w-full">
{rows.map((row) => (
<HexRow key={row.address} {...row} />
))}
</div>
);
}
5 changes: 4 additions & 1 deletion gh-pages/src/components/Inspector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ export function Inspector({ name, url, onUnload }: InspectorProps) {
{f.type === "image" && (
<img className="m-auto max-h-fit" src={f.url} />
)}
{f.type === "iwa" && <IWorkArchiveInspector file={f} />}
{f.type === "iwa" && <IWorkArchiveInspector file={f} onToggle={() => dispatch({
type: "toggle-file",
path: f.path,
})} />}
</FileFrame>
))}
</Fragment>
Expand Down
10 changes: 5 additions & 5 deletions gh-pages/src/components/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ export function SearchBar({ category, onCategoryChange }: SearchBarProps) {
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
fillRule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
clipRule="evenodd"
></path>
</svg>
</button>
Expand Down Expand Up @@ -94,9 +94,9 @@ export function SearchBar({ category, onCategoryChange }: SearchBarProps) {
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
></path>
</svg>
Expand Down
37 changes: 31 additions & 6 deletions gh-pages/src/components/iWorkArchiveInspector.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,38 @@
import { Fragment} from 'react'
import { Fragment, useEffect } from "react";
import { ChunkJsonViewer } from "./ChunkJsonViewer";
import { HexViewer } from "./HexViewer";
import { IwaFileState } from "./statemachine/states";

export interface IWorkArchiveInspectorProps {
file: IwaFileState;
onToggle: () => void;
}

export function IWorkArchiveInspector({file}: IWorkArchiveInspectorProps) {
export function IWorkArchiveInspector({ file, onToggle }: IWorkArchiveInspectorProps) {
const { chunks } = file;
return <>
{chunks.map(c => <div>0x{c.startAddress.toString(16)}:</div>).reduce((a,b) => <Fragment>{[a, <hr className='my-2'/>, b]}</Fragment>)}
</>
}

return (
<>
{!file.open && <button onClick={onToggle}>Open</button>}
{file.open && chunks
.map((c, index) => (
<Fragment key={index}>
<div className="font-mono text-xs">
Chunk {index + 1} @ 0x{c.startAddress.toString(16)}:
</div>
<div className="grid">
<div className="grid col-start-1 col-end-2">
<HexViewer startAddress={c.startAddress} data={c.data} regions={[]}/>
</div>
<div className="grid col-start-2 col-end-3">
<ChunkJsonViewer data={c.data}/>
</div>
</div>
</Fragment>
))
.reduce((a, b) => (
<Fragment>{[a, <hr className="my-2" />, b]}</Fragment>
))}
</>
);
}
9 changes: 7 additions & 2 deletions gh-pages/src/components/statemachine/actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type ActionType = 'add-file'|'add-chunk';
export type ActionType = 'add-file'|'add-chunk'|'toggle-file';

export interface ActionBase {
type: ActionType;
Expand All @@ -17,4 +17,9 @@ export interface AddChunkAction extends ActionBase {
data: Uint8Array;
}

export type Action = AddFileAction | AddChunkAction;
export interface ToggleFileAction extends ActionBase {
type: 'toggle-file';
path: string;
}

export type Action = AddFileAction | AddChunkAction | ToggleFileAction;
23 changes: 21 additions & 2 deletions gh-pages/src/components/statemachine/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ export function reducer(state: InspectorState, action: Action): InspectorState {
...fileCommon,
type: 'iwa',
chunks: [],
buffer: action.data
buffer: action.data,
open: false
};
break;
default:
Expand All @@ -59,7 +60,8 @@ export function reducer(state: InspectorState, action: Action): InspectorState {
const iwaFile = state.files.find(f => f.path === action.path);
if (iwaFile && iwaFile.type === 'iwa') {
const chunk: ChunkState = {
startAddress: action.startAddress
startAddress: action.startAddress,
data: action.data
};
return {
...state,
Expand All @@ -76,6 +78,23 @@ export function reducer(state: InspectorState, action: Action): InspectorState {
};
}
return state;
case "toggle-file":
const fileToToggleIndex = state.files.findIndex(f => f.path === action.path);
const fileToToggle = state.files[fileToToggleIndex];
if (fileToToggle && fileToToggle.type === 'iwa') {
return {
...state,
files: [
...state.files.slice(0, fileToToggleIndex),
{
...fileToToggle,
open: !fileToToggle.open
},
...state.files.slice(fileToToggleIndex + 1)
]
};
}
return state;
default:
return state;
}
Expand Down
2 changes: 2 additions & 0 deletions gh-pages/src/components/statemachine/states.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ export interface FileStateBase {

export interface IwaFileState extends FileStateBase {
type: 'iwa';
open: boolean;
chunks: ChunkState[];
buffer: Uint8Array
}

export interface ChunkState {
startAddress: number;
data: Uint8Array;
}

export interface XmlFileState extends FileStateBase {
Expand Down
3 changes: 2 additions & 1 deletion gh-pages/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"incremental": true,
"paths": {
"@/*": ["./src/*"]
}
},
"downlevelIteration": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
Expand Down

0 comments on commit 14ddf84

Please sign in to comment.