Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update #15

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions binspec-visualizer/app/components/data-segment-details.hbs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<div ...attributes>
<div class="flex items-center w-full">
<DataSegmentDetails::TitleWithBreadcrumbs
@highlightedSegment={{@highlightedSegment}}
@segment={{@segment}}
@onSegmentSelect={{@onSegmentSelect}}
@onSegmentMouseEnter={{@onSegmentMouseEnter}}
Expand All @@ -14,22 +15,22 @@
{{/if}}
</div>

{{#if @segment.explanationMarkdown}}
<div class="prose prose-invert prose-sm mt-3">
{{markdown-to-html @segment.explanationMarkdown}}
</div>
{{/if}}

{{#if (gt @segment.children.length 0)}}
<DataSegmentDetails::Children
class="mt-1"
class="mt-3"
@segment={{@segment}}
@onSegmentSelect={{@onSegmentSelect}}
@onSegmentMouseEnter={{@onSegmentMouseEnter}}
@onSegmentMouseLeave={{@onSegmentMouseLeave}}
/>
{{/if}}

{{#if @segment.explanationMarkdown}}
<div class="prose prose-invert prose-sm mt-2">
{{markdown-to-html @segment.explanationMarkdown}}
</div>
{{/if}}

{{#if @segment.isLeafSegment}}
<div class="mt-3 text-xs uppercase text-zinc-500 font-semibold">
{{@segment.lengthInBytes}}
Expand Down
1 change: 1 addition & 0 deletions binspec-visualizer/app/components/data-segment-details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type Signature = {
Args: {
data: Uint8Array;
segment: DataSegment;
highlightedSegment?: DataSegment;
onSegmentSelect: (segment: DataSegment) => void;
onSegmentMouseEnter: (
section: NonNullable<HoverStateService['initiatedFromSection']>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type HoverStateService from 'binspec-visualizer/services/hover-state';

type Signature = {
Args: {
highlightedSegment?: DataSegment;
segment: DataSegment;
onSegmentSelect: (segment: DataSegment) => void;
onSegmentMouseEnter: (
Expand All @@ -29,9 +30,15 @@ export default class TitleWithBreadcrumbsComponent extends Component<Signature>
}

get titleTextColorClasses(): string {
return this.hoveredSegment === this.args.segment
? 'text-blue-400'
: 'text-yellow-300';
if (this.hoveredSegment?.equals(this.args.segment)) {
return 'text-sky-400';
}

if (this.args.highlightedSegment?.equals(this.args.segment)) {
return 'text-yellow-300';
}

return 'text-zinc-100';
}

get visibleAncestors(): DataSegment[] {
Expand Down
12 changes: 12 additions & 0 deletions binspec-visualizer/app/components/format-documentation.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<div class="flex flex-col gap-8">
{{#each @segments as |segment|}}
<FormatDocumentation::Segment
@data={{@data}}
@segment={{segment}}
@highlightedSegment={{@highlightedSegment}}
@onSegmentSelect={{@onSegmentSelect}}
@onSegmentMouseEnter={{@onSegmentMouseEnter}}
@onSegmentMouseLeave={{@onSegmentMouseLeave}}
/>
{{/each}}
</div>
27 changes: 27 additions & 0 deletions binspec-visualizer/app/components/format-documentation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Component from '@glimmer/component';
import type { DataSegment } from 'binspec-visualizer/lib/data-segment';
import type HoverStateService from 'binspec-visualizer/services/hover-state';

type Signature = {
Args: {
data: Uint8Array;
segments: DataSegment[];
highlightedSegment?: DataSegment;
onSegmentSelect: (segment: DataSegment) => void;
onSegmentMouseEnter: (
section: NonNullable<HoverStateService['initiatedFromSection']>,
segment: DataSegment,
byteIndex?: number,
event?: MouseEvent,
) => void;
onSegmentMouseLeave: () => void;
};
};

export default class FormatDocumentation extends Component<Signature> {}

declare module '@glint/environment-ember-loose/registry' {
export default interface Registry {
FormatDocumentation: typeof FormatDocumentation;
}
}
91 changes: 91 additions & 0 deletions binspec-visualizer/app/components/format-documentation/segment.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<div ...attributes>
<div
class="pl-4 border-l-2
{{if
(segment-eq @segment @highlightedSegment)
'border-yellow-300'
'border-transparent hover:bg-zinc-700/60'
}}"
role={{if
(segment-eq @segment @highlightedSegment)
"presentation"
"button"
}}
{{on "click" (fn @onSegmentSelect @segment)}}
>
<div class="flex items-center w-full">
<DataSegmentDetails::TitleWithBreadcrumbs
@highlightedSegment={{@highlightedSegment}}
@segment={{@segment}}
@onSegmentSelect={{@onSegmentSelect}}
@onSegmentMouseEnter={{@onSegmentMouseEnter}}
@onSegmentMouseLeave={{@onSegmentMouseLeave}}
/>

{{#if (has-block "topRight")}}
<div class="flex-grow flex items-center justify-end pl-2">
{{yield to="topRight"}}
</div>
{{/if}}
</div>

{{#if @segment.explanationMarkdown}}
<div class="prose prose-invert prose-sm mt-3">
{{markdown-to-html @segment.explanationMarkdown}}
</div>
{{/if}}

{{#if (gt @segment.children.length 0)}}
<DataSegmentDetails::Children
class="mt-3"
@segment={{@segment}}
@onSegmentSelect={{@onSegmentSelect}}
@onSegmentMouseEnter={{@onSegmentMouseEnter}}
@onSegmentMouseLeave={{@onSegmentMouseLeave}}
/>
{{/if}}

{{#if
(and @segment.isLeafSegment (segment-eq @segment @highlightedSegment))
}}
<div class="mt-3 text-xs uppercase text-zinc-500 font-semibold">
{{@segment.lengthInBytes}}
{{if (eq @segment.lengthInBytes 1) "byte" "bytes"}}:
</div>

<HexPreview
class="mt-2 w-full"
@data={{@data}}
@endByteIndex={{this.previewEndByteIndex}}
@highlightedSegment={{@segment}}
@onSegmentMouseEnter={{@onSegmentMouseEnter}}
@onSegmentMouseLeave={{@onSegmentMouseLeave}}
@onSegmentSelect={{@onSegmentSelect}}
@section="segment-details-hexdump"
@segments={{array @segment}}
@startByteIndex={{@segment.startByteIndex}}
>
<:lastBytePreview>
{{#if this.previewIsTruncated}}
<div class="flex items-center justify-center">
<span class="text-lg text-zinc-500">⋯</span>
</div>
{{/if}}
</:lastBytePreview>
</HexPreview>
{{/if}}
</div>

<div class="flex flex-col gap-4 mt-3">
{{#each @segment.children as |child|}}
<FormatDocumentation::Segment
@data={{@data}}
@highlightedSegment={{@highlightedSegment}}
@onSegmentSelect={{@onSegmentSelect}}
@onSegmentMouseEnter={{@onSegmentMouseEnter}}
@onSegmentMouseLeave={{@onSegmentMouseLeave}}
@segment={{child}}
/>
{{/each}}
</div>
</div>
55 changes: 55 additions & 0 deletions binspec-visualizer/app/components/format-documentation/segment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { service } from '@ember/service';
import Component from '@glimmer/component';
import type { DataSegment } from 'binspec-visualizer/lib/data-segment';
import type HoverStateService from 'binspec-visualizer/services/hover-state';

type Signature = {
Args: {
data: Uint8Array;
segment: DataSegment;
highlightedSegment?: DataSegment;
onSegmentSelect: (segment: DataSegment) => void;
onSegmentMouseEnter: (
section: NonNullable<HoverStateService['initiatedFromSection']>,
segment: DataSegment,
byteIndex?: number,
event?: MouseEvent,
) => void;
onSegmentMouseLeave: () => void;
};

Element: HTMLDivElement;

Blocks: {
topRight?: [];
};
};

export default class FormatDocumentationSegment extends Component<Signature> {
@service declare hoverState: HoverStateService;

get hoveredSegment(): DataSegment | undefined {
return this.hoverState.segment;
}

get titleTextColorClasses(): string {
return 'text-yellow-300';
}

get previewEndByteIndex(): number {
return Math.min(
this.args.segment.endByteIndex,
this.args.segment.startByteIndex + 14,
);
}

get previewIsTruncated(): boolean {
return this.args.segment.endByteIndex > this.previewEndByteIndex;
}
}

declare module '@glint/environment-ember-loose/registry' {
export default interface Registry {
'FormatDocumentation::Segment': typeof FormatDocumentationSegment;
}
}
2 changes: 1 addition & 1 deletion binspec-visualizer/app/controllers/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default class FormatController extends Controller {

get highlightedSegment(): DataSegment | undefined {
if (!this.highlightQueryParam) {
return this.model.format.segments[0]!.firstLeafSegment!;
return this.model.format.segments[0]!;
}

const startByteIndexStr = this.highlightQueryParam.split('-')[0];
Expand Down
98 changes: 9 additions & 89 deletions binspec-visualizer/app/templates/format.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,95 +7,15 @@
<h2 class="mb-4 text-xl md:text-2xl font-medium text-white">
{{@model.format.name}}
</h2>
<div
class="rounded-md border border-zinc-700/60 flex-grow w-full flex flex-col min-h-0"
id="raw-container"
{{click-outside this.handleClickOutside}}
>
<div class="p-4 flex-grow overflow-y-auto min-h-0">
{{#if this.highlightedSegment}}
<DataSegmentDetails
@data={{this.data}}
@segment={{this.highlightedSegment}}
@onSegmentSelect={{this.handleSegmentSelected}}
@onSegmentMouseEnter={{this.handleSegmentMouseEnter}}
@onSegmentMouseLeave={{this.handleSegmentMouseLeave}}
>
<:topRight>
<DataSegmentDetails::SiblingSwitcherContainer
class="flex-shrink-0"
@nextSegment={{this.nextSegment}}
@previousSegment={{this.previousSegment}}
@onSegmentSelect={{this.handleSegmentSelected}}
@onSegmentMouseEnter={{this.handleSegmentMouseEnter}}
@onSegmentMouseLeave={{this.handleSegmentMouseLeave}}
/>
</:topRight>
</DataSegmentDetails>
{{/if}}
</div>
<div class="text-right w-full text-xs text-zinc-600 pb-1 px-2">
{{#if this.hoveredSegment}}
{{#if (eq this.hoveredSegment.lengthInBytes 1)}}
1 byte
{{else}}
{{this.hoveredSegment.lengthInBytes}}
bytes
{{/if}}
{{else if this.highlightedSegment}}
{{#if (eq this.highlightedSegment.lengthInBytes 1)}}
1 byte
{{else}}
{{this.highlightedSegment.lengthInBytes}}
bytes
{{/if}}
{{else}}
{{this.data.length}}
bytes
{{/if}}
</div>
<div
class="flex items-stretch border rounded mx-1 mb-1 border-zinc-700/60 relative"
>
<div
class="absolute top-0 left-0 right-0 h-10 bg-gradient-to-b from-zinc-800 from-30% to-zinc-800/0 pointer-events-none"
></div>
<div
class="absolute bottom-0 left-0 right-0 h-10 bg-gradient-to-t from-zinc-800 from-30% to-zinc-800/0 pointer-events-none"
></div>
<div
class="absolute h-6 -top-3 left-1/2 -translate-x-1/2 text-zinc-500 text-xs bg-zinc-800 px-2 rounded-md flex items-center"
>
Raw Bytes
</div>
<div class="overflow-y-auto h-[150px] w-full py-12 px-4">
<HexPreview
id="hexdump-container"
@section="root-hexdump"
@byteIndexForInterstitial={{if
this.highlightedSegment
this.highlightedSegment.startByteIndex
0
}}
@data={{this.data}}
@segments={{this.segments}}
@highlightedSegment={{this.highlightedSegment}}
@onSegmentSelect={{this.handleSegmentSelected}}
@onSegmentMouseEnter={{this.handleSegmentMouseEnter}}
@onSegmentMouseLeave={{this.handleSegmentMouseLeave}}
>
<:interstitial>
{{#if this.highlightedSegment}}
<div
id="highlighted-segment-interstitial"
class="scroll-mt-[50px]"
>
</div>
{{/if}}
</:interstitial>
</HexPreview>
</div>
</div>
<div class="p-4 flex-grow min-h-0">
<FormatDocumentation
@data={{this.data}}
@segments={{this.segments}}
@highlightedSegment={{this.highlightedSegment}}
@onSegmentSelect={{this.handleSegmentSelected}}
@onSegmentMouseEnter={{this.handleSegmentMouseEnter}}
@onSegmentMouseLeave={{this.handleSegmentMouseLeave}}
/>
</div>
</div>
</div>