mirror of
https://github.com/waaraawa/ByteGrid.git
synced 2026-07-22 06:41:47 +00:00
feat(core): add automatic color assignment for fields
- Add autoColor option (default: true)
- true: Auto-assign colors to fields without explicit colors
- false: Use gray for fields without explicit colors
- Auto color sequence: blue, cyan, yellow, green, orange, purple, mint, pink
- Padding/reserved fields always use gray
- Explicit colors always take precedence
Examples & Documentation:
- Add 4 example files (basic, manual, mixed, interactive guide)
- Update examples/README.md with Auto Color section
- Add Color Options explanation
Tests:
- Add 8 new tests (5 layoutEngine, 3 parser)
- Update existing test for autoColor: false
This commit is contained in:
parent
39f3e84fac
commit
482b458370
10 changed files with 570 additions and 8 deletions
|
|
@ -61,6 +61,25 @@ This folder contains example files for the ByteGrid plugin.
|
|||
- **Bitfield example**: 16 CPU flags
|
||||
- CF, ZF, SF, IF, DF, OF, IOPL, etc.
|
||||
|
||||
### Auto Color Examples
|
||||
|
||||
#### 8. auto-color-examples.md
|
||||
- **Interactive guide** with 4 examples showing automatic color assignment
|
||||
- Open this file in Obsidian to see live examples
|
||||
- Explains auto color modes and behavior
|
||||
|
||||
#### 9. auto-color-basic.yaml
|
||||
- Basic auto color example (8 fields, 8 colors)
|
||||
- Default behavior: colors assigned automatically
|
||||
|
||||
#### 10. auto-color-manual.yaml
|
||||
- Manual color mode (`autoColor: false`)
|
||||
- Only explicit colors shown, others gray
|
||||
|
||||
#### 11. auto-color-mixed.yaml
|
||||
- Mixed mode: combine auto and manual colors
|
||||
- Explicit colors take precedence
|
||||
|
||||
## Important Notes
|
||||
|
||||
⚠️ **Watch Out for Indentation When Copying**
|
||||
|
|
@ -81,32 +100,56 @@ To visualize a new structure:
|
|||
name: Structure Name
|
||||
size: total byte size
|
||||
layout: 16 # bytes per row (optional, default: 16)
|
||||
layoutUnit: byte # byte or bit (optional, auto-inferred from suffix)
|
||||
|
||||
# Color options
|
||||
autoColor: true # auto-assign colors (optional, default: true)
|
||||
colorScheme: default # default, dark, or light (optional, default: default)
|
||||
|
||||
# Legend options
|
||||
legendPosition: right # right, left, bottom, none (optional, default: right)
|
||||
legendColumns: 1 # number of columns in legend (optional, default: 1)
|
||||
|
||||
# Other options
|
||||
showFooter: true # show/hide footer (optional, default: true)
|
||||
|
||||
fields:
|
||||
- offset: 0-3
|
||||
name: FieldName
|
||||
type: uint32_t
|
||||
color: blue # blue, cyan, yellow, green, orange, purple, mint, pink, gray
|
||||
color: blue # blue, cyan, yellow, green, orange, purple, mint, pink, gray (optional)
|
||||
description: "Description" # optional
|
||||
```
|
||||
|
||||
### Color Options Explained
|
||||
|
||||
**autoColor** (default: `true`):
|
||||
- `true`: Fields without explicit colors get auto-assigned (blue, cyan, yellow, green, orange, purple, mint, pink)
|
||||
- `false`: Fields without explicit colors default to gray
|
||||
|
||||
**colorScheme** (default: `default`):
|
||||
- `default`: Original pastel colors
|
||||
- `dark`: Reduced saturation and lightness (easier on eyes)
|
||||
- `light`: Increased lightness (better for bright backgrounds)
|
||||
|
||||
**Tip**: Start with `autoColor: true` and only specify colors for fields you want to emphasize!
|
||||
|
||||
## Bit-Level Layout Examples
|
||||
|
||||
### 8. simple-bit-layout.yaml
|
||||
### 12. simple-bit-layout.yaml
|
||||
- Basic bit-level layout test (16 bits)
|
||||
- **Suffix notation**: `size: 16b`, `layout: 16b`, `offset: 0-7b`
|
||||
- `layoutUnit` can be omitted (auto-inferred from suffix)
|
||||
|
||||
### 9. nibble-test.yaml
|
||||
### 13. nibble-test.yaml
|
||||
- 4-bit field (nibble) test
|
||||
- Each nibble represented independently
|
||||
|
||||
### 10. mixed-bit-byte.yaml
|
||||
### 14. mixed-bit-byte.yaml
|
||||
- Mixed bit and byte offsets
|
||||
- `0-3b` (bit), `1B` (Byte), `2-3` (byte, default)
|
||||
|
||||
### 11. ipv4-bit-layout.yaml
|
||||
### 15. ipv4-bit-layout.yaml
|
||||
- IPv4 header in bit-level representation
|
||||
- Sub-byte fields like Version(4bit) + IHL(4bit)
|
||||
|
||||
|
|
|
|||
38
examples/auto-color-basic.yaml
Normal file
38
examples/auto-color-basic.yaml
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
name: Auto Color Basic Example
|
||||
size: 32
|
||||
layout: 16
|
||||
# autoColor: true is the default
|
||||
|
||||
fields:
|
||||
- offset: 0-3
|
||||
name: Field1
|
||||
type: uint32_t
|
||||
description: "Auto-assigned blue"
|
||||
- offset: 4-7
|
||||
name: Field2
|
||||
type: uint32_t
|
||||
description: "Auto-assigned cyan"
|
||||
- offset: 8-11
|
||||
name: Field3
|
||||
type: uint32_t
|
||||
description: "Auto-assigned yellow"
|
||||
- offset: 12-15
|
||||
name: Field4
|
||||
type: uint32_t
|
||||
description: "Auto-assigned green"
|
||||
- offset: 16-19
|
||||
name: Field5
|
||||
type: uint32_t
|
||||
description: "Auto-assigned orange"
|
||||
- offset: 20-23
|
||||
name: Field6
|
||||
type: uint32_t
|
||||
description: "Auto-assigned purple"
|
||||
- offset: 24-27
|
||||
name: Field7
|
||||
type: uint32_t
|
||||
description: "Auto-assigned mint"
|
||||
- offset: 28-31
|
||||
name: Field8
|
||||
type: uint32_t
|
||||
description: "Auto-assigned pink"
|
||||
215
examples/auto-color-examples.md
Normal file
215
examples/auto-color-examples.md
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
# Auto Color Examples
|
||||
|
||||
ByteGrid supports automatic color assignment for fields. This feature makes it easy to create visualizations without manually specifying colors for each field.
|
||||
|
||||
## Example 1: Basic Auto Color (Default)
|
||||
|
||||
When `autoColor` is enabled (default), fields without explicit colors are automatically assigned distinct colors in sequence: blue, cyan, yellow, green, orange, purple, mint, pink.
|
||||
|
||||
```bytegrid
|
||||
name: WAV Header (Auto Color)
|
||||
size: 44
|
||||
layout: 16
|
||||
|
||||
fields:
|
||||
- offset: 0-3
|
||||
name: ChunkID
|
||||
type: char[4]
|
||||
description: "RIFF magic number"
|
||||
- offset: 4-7
|
||||
name: ChunkSize
|
||||
type: uint32_t
|
||||
description: "File size - 8"
|
||||
- offset: 8-11
|
||||
name: Format
|
||||
type: char[4]
|
||||
description: "WAVE format"
|
||||
- offset: 12-15
|
||||
name: Subchunk1ID
|
||||
type: char[4]
|
||||
description: "fmt subchunk"
|
||||
- offset: 16-19
|
||||
name: Subchunk1Size
|
||||
type: uint32_t
|
||||
description: "Size of fmt chunk"
|
||||
- offset: 20-21
|
||||
name: AudioFormat
|
||||
type: uint16_t
|
||||
description: "Audio format (1=PCM)"
|
||||
- offset: 22-23
|
||||
name: NumChannels
|
||||
type: uint16_t
|
||||
description: "Number of channels"
|
||||
- offset: 24-27
|
||||
name: SampleRate
|
||||
type: uint32_t
|
||||
description: "Sample rate (Hz)"
|
||||
- offset: 28-31
|
||||
name: ByteRate
|
||||
type: uint32_t
|
||||
description: "Byte rate"
|
||||
```
|
||||
|
||||
**Result**: Each field gets a different color automatically!
|
||||
|
||||
---
|
||||
|
||||
## Example 2: Manual Color Mode
|
||||
|
||||
When `autoColor: false`, only explicitly specified colors are used. Fields without colors default to gray.
|
||||
|
||||
```bytegrid
|
||||
name: TCP Header (Manual Colors)
|
||||
size: 20
|
||||
layout: 16
|
||||
autoColor: false
|
||||
|
||||
fields:
|
||||
- offset: 0-1
|
||||
name: SourcePort
|
||||
type: uint16_t
|
||||
color: blue
|
||||
description: "Source port number"
|
||||
- offset: 2-3
|
||||
name: DestPort
|
||||
type: uint16_t
|
||||
color: cyan
|
||||
description: "Destination port number"
|
||||
- offset: 4-7
|
||||
name: SeqNumber
|
||||
type: uint32_t
|
||||
description: "Sequence number (no color = gray)"
|
||||
- offset: 8-11
|
||||
name: AckNumber
|
||||
type: uint32_t
|
||||
description: "Acknowledgment number (gray)"
|
||||
- offset: 12-13
|
||||
name: Flags
|
||||
type: uint16_t
|
||||
color: yellow
|
||||
description: "Flags and offset"
|
||||
- offset: 14-15
|
||||
name: WindowSize
|
||||
type: uint16_t
|
||||
description: "Window size (gray)"
|
||||
```
|
||||
|
||||
**Result**: Only SourcePort (blue), DestPort (cyan), and Flags (yellow) have colors. Others are gray.
|
||||
|
||||
---
|
||||
|
||||
## Example 3: Mixed Mode (Auto + Manual)
|
||||
|
||||
You can combine automatic colors with explicit colors. Explicit colors always take precedence.
|
||||
|
||||
```bytegrid
|
||||
name: Custom Packet (Mixed Colors)
|
||||
size: 32
|
||||
layout: 16
|
||||
|
||||
fields:
|
||||
- offset: 0-3
|
||||
name: MagicNumber
|
||||
type: uint32_t
|
||||
color: pink
|
||||
description: "Custom magic number (explicit pink)"
|
||||
- offset: 4-7
|
||||
name: Version
|
||||
type: uint32_t
|
||||
description: "Protocol version (auto: cyan)"
|
||||
- offset: 8-11
|
||||
name: Length
|
||||
type: uint32_t
|
||||
description: "Packet length (auto: yellow)"
|
||||
- offset: 12-15
|
||||
name: Checksum
|
||||
type: uint32_t
|
||||
color: mint
|
||||
description: "CRC32 checksum (explicit mint)"
|
||||
- offset: 16-19
|
||||
name: Timestamp
|
||||
type: uint32_t
|
||||
description: "Unix timestamp (auto: green)"
|
||||
- offset: 20-23
|
||||
name: SourceID
|
||||
type: uint32_t
|
||||
description: "Source identifier (auto: orange)"
|
||||
- offset: 24-27
|
||||
name: DestID
|
||||
type: uint32_t
|
||||
description: "Destination ID (auto: purple)"
|
||||
- offset: 28-31
|
||||
name: Payload
|
||||
type: uint32_t
|
||||
description: "Payload data (auto: mint again, cycles)"
|
||||
```
|
||||
|
||||
**Result**: MagicNumber is pink (explicit), Checksum is mint (explicit), others are auto-assigned.
|
||||
|
||||
---
|
||||
|
||||
## Example 4: With Padding/Reserved Fields
|
||||
|
||||
Padding and reserved fields are always gray, regardless of `autoColor` setting.
|
||||
|
||||
```bytegrid
|
||||
name: File Header (With Padding)
|
||||
size: 24
|
||||
layout: 16
|
||||
|
||||
fields:
|
||||
- offset: 0-3
|
||||
name: Signature
|
||||
type: char[4]
|
||||
description: "File signature (auto: blue)"
|
||||
- offset: 4-7
|
||||
name: Version
|
||||
type: uint32_t
|
||||
description: "File version (auto: cyan)"
|
||||
- offset: 8-11
|
||||
name: Reserved1
|
||||
type: reserved
|
||||
description: "Reserved for future use (always gray)"
|
||||
- offset: 12-15
|
||||
name: DataOffset
|
||||
type: uint32_t
|
||||
description: "Offset to data (auto: green)"
|
||||
- offset: 16-19
|
||||
name: DataSize
|
||||
type: uint32_t
|
||||
description: "Size of data (auto: orange)"
|
||||
- offset: 20-23
|
||||
name: Padding
|
||||
type: padding
|
||||
description: "Alignment padding (always gray)"
|
||||
```
|
||||
|
||||
**Result**: Reserved1 and Padding are gray (special types), others are auto-colored.
|
||||
|
||||
---
|
||||
|
||||
## Color Cycle
|
||||
|
||||
When you have more than 8 fields, colors cycle back to the beginning:
|
||||
|
||||
1. blue
|
||||
2. cyan
|
||||
3. yellow
|
||||
4. green
|
||||
5. orange
|
||||
6. purple
|
||||
7. mint
|
||||
8. pink
|
||||
9. **blue** (cycles back)
|
||||
10. **cyan**
|
||||
11. ...
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
- **Default behavior**: `autoColor: true` (automatic colors)
|
||||
- **Manual mode**: `autoColor: false` (only explicit colors, others gray)
|
||||
- **Mixed mode**: Combine auto and manual colors
|
||||
- **Special fields**: `reserved` and `padding` are always gray
|
||||
- **8 colors**: blue, cyan, yellow, green, orange, purple, mint, pink
|
||||
33
examples/auto-color-manual.yaml
Normal file
33
examples/auto-color-manual.yaml
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
name: Manual Color Mode Example
|
||||
size: 24
|
||||
layout: 16
|
||||
autoColor: false # Disable auto color assignment
|
||||
|
||||
fields:
|
||||
- offset: 0-3
|
||||
name: Header
|
||||
type: uint32_t
|
||||
color: blue
|
||||
description: "Explicit blue color"
|
||||
- offset: 4-7
|
||||
name: NoColor1
|
||||
type: uint32_t
|
||||
description: "No color specified = gray"
|
||||
- offset: 8-11
|
||||
name: Important
|
||||
type: uint32_t
|
||||
color: yellow
|
||||
description: "Explicit yellow to highlight"
|
||||
- offset: 12-15
|
||||
name: NoColor2
|
||||
type: uint32_t
|
||||
description: "No color specified = gray"
|
||||
- offset: 16-19
|
||||
name: Footer
|
||||
type: uint32_t
|
||||
color: cyan
|
||||
description: "Explicit cyan color"
|
||||
- offset: 20-23
|
||||
name: NoColor3
|
||||
type: uint32_t
|
||||
description: "No color specified = gray"
|
||||
36
examples/auto-color-mixed.yaml
Normal file
36
examples/auto-color-mixed.yaml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
name: Mixed Color Mode Example
|
||||
size: 28
|
||||
layout: 16
|
||||
# autoColor: true (default) - mix auto and manual colors
|
||||
|
||||
fields:
|
||||
- offset: 0-3
|
||||
name: MagicNumber
|
||||
type: uint32_t
|
||||
color: pink
|
||||
description: "Custom color (explicit pink)"
|
||||
- offset: 4-7
|
||||
name: Version
|
||||
type: uint32_t
|
||||
description: "Auto-assigned (cyan)"
|
||||
- offset: 8-11
|
||||
name: Length
|
||||
type: uint32_t
|
||||
description: "Auto-assigned (yellow)"
|
||||
- offset: 12-15
|
||||
name: Reserved
|
||||
type: reserved
|
||||
description: "Always gray for reserved"
|
||||
- offset: 16-19
|
||||
name: Checksum
|
||||
type: uint32_t
|
||||
color: mint
|
||||
description: "Custom color (explicit mint)"
|
||||
- offset: 20-23
|
||||
name: Timestamp
|
||||
type: uint32_t
|
||||
description: "Auto-assigned (orange)"
|
||||
- offset: 24-27
|
||||
name: Data
|
||||
type: uint32_t
|
||||
description: "Auto-assigned (purple)"
|
||||
|
|
@ -17,6 +17,12 @@ export function createLayout(config: ByteGridConfig): LayoutBlock[] {
|
|||
const layoutUnit = config.layoutUnit || 'byte';
|
||||
const blocks: LayoutBlock[] = [];
|
||||
|
||||
// Auto color enabled by default
|
||||
const autoColor = config.autoColor !== undefined ? config.autoColor : true;
|
||||
|
||||
// Colors for auto-assignment (excluding gray for non-padding fields)
|
||||
const autoColors: ColorName[] = ['blue', 'cyan', 'yellow', 'green', 'orange', 'purple', 'mint', 'pink'];
|
||||
|
||||
// Convert offset to bits for unified processing
|
||||
const toBits = (offset: ReturnType<typeof parseOffset>): { start: number; end: number; size: number } => {
|
||||
if (layoutUnit === 'bit') {
|
||||
|
|
@ -31,12 +37,25 @@ export function createLayout(config: ByteGridConfig): LayoutBlock[] {
|
|||
return { start: offset.start, end: offset.end, size: offset.size };
|
||||
};
|
||||
|
||||
for (const field of config.fields) {
|
||||
for (let fieldIndex = 0; fieldIndex < config.fields.length; fieldIndex++) {
|
||||
const field = config.fields[fieldIndex];
|
||||
const offset = parseOffset(field.offset);
|
||||
const offsetInUnits = toBits(offset);
|
||||
const color = (field.color || 'gray') as ColorName;
|
||||
const isPadding = field.type === 'reserved' || field.type === 'padding';
|
||||
|
||||
// Determine color
|
||||
let color: ColorName;
|
||||
if (field.color) {
|
||||
// Explicit color specified
|
||||
color = field.color as ColorName;
|
||||
} else if (autoColor && !isPadding) {
|
||||
// Auto-assign color for non-padding fields
|
||||
color = autoColors[fieldIndex % autoColors.length];
|
||||
} else {
|
||||
// Default to gray (manual mode or padding)
|
||||
color = 'gray';
|
||||
}
|
||||
|
||||
// Check if field spans multiple rows
|
||||
const startRow = Math.floor(offsetInUnits.start / layout);
|
||||
const endRow = Math.floor(offsetInUnits.end / layout);
|
||||
|
|
|
|||
|
|
@ -242,6 +242,11 @@ export function parse(source: string): ByteGridConfig {
|
|||
? (obj.colorScheme as 'default' | 'dark' | 'light')
|
||||
: undefined;
|
||||
|
||||
// Parse autoColor (optional, default: true)
|
||||
const autoColor = obj.autoColor !== undefined && typeof obj.autoColor === 'boolean'
|
||||
? obj.autoColor
|
||||
: undefined;
|
||||
|
||||
// Parse legendPosition (optional)
|
||||
const legendPosition = obj.legendPosition && typeof obj.legendPosition === 'string'
|
||||
? (obj.legendPosition as 'right' | 'left' | 'bottom' | 'none')
|
||||
|
|
@ -266,6 +271,7 @@ export function parse(source: string): ByteGridConfig {
|
|||
layout,
|
||||
layoutUnit: finalLayoutUnit,
|
||||
colorScheme,
|
||||
autoColor,
|
||||
legendPosition,
|
||||
legendColumns,
|
||||
showFooter,
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ export interface ByteGridConfig {
|
|||
layout?: number; // Units per row (default: 16), unit depends on layoutUnit
|
||||
layoutUnit?: LayoutUnit; // 'byte' (default) or 'bit'
|
||||
colorScheme?: ColorScheme;
|
||||
autoColor?: boolean; // Auto-assign colors to fields (default: true)
|
||||
legendPosition?: LegendPosition; // 'right' (default), 'left', 'bottom', or 'none'
|
||||
legendColumns?: number; // Number of columns in legend (default: 1)
|
||||
showFooter?: boolean; // Show footer with total size and layout info (default: true)
|
||||
|
|
|
|||
|
|
@ -109,10 +109,11 @@ describe('LayoutEngine', () => {
|
|||
expect(blocks[2].offsetEnd).toBe(11);
|
||||
});
|
||||
|
||||
it('should default to gray color for fields without color', () => {
|
||||
it('should default to gray color for fields without color when autoColor is false', () => {
|
||||
const config: ByteGridConfig = {
|
||||
name: 'Test',
|
||||
size: 8,
|
||||
autoColor: false,
|
||||
fields: [
|
||||
{ offset: '0-3', name: 'Field1', type: 'uint32_t' },
|
||||
],
|
||||
|
|
@ -384,4 +385,124 @@ describe('LayoutEngine', () => {
|
|||
expect(blocks[1].span).toBe(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('autoColor feature', () => {
|
||||
it('should auto-assign colors when autoColor is true (default)', () => {
|
||||
const config: ByteGridConfig = {
|
||||
name: 'Test',
|
||||
size: 16,
|
||||
layout: 16,
|
||||
fields: [
|
||||
{ offset: '0-3', name: 'Field1', type: 'uint32_t' }, // No color specified
|
||||
{ offset: '4-7', name: 'Field2', type: 'uint32_t' }, // No color specified
|
||||
{ offset: '8-11', name: 'Field3', type: 'uint32_t' }, // No color specified
|
||||
],
|
||||
};
|
||||
|
||||
const blocks = createLayout(config);
|
||||
|
||||
expect(blocks).toHaveLength(3);
|
||||
// Should auto-assign: blue, cyan, yellow
|
||||
expect(blocks[0].color).toBe('blue');
|
||||
expect(blocks[1].color).toBe('cyan');
|
||||
expect(blocks[2].color).toBe('yellow');
|
||||
});
|
||||
|
||||
it('should use gray when autoColor is false and no color specified', () => {
|
||||
const config: ByteGridConfig = {
|
||||
name: 'Test',
|
||||
size: 16,
|
||||
layout: 16,
|
||||
autoColor: false,
|
||||
fields: [
|
||||
{ offset: '0-3', name: 'Field1', type: 'uint32_t' }, // No color specified
|
||||
{ offset: '4-7', name: 'Field2', type: 'uint32_t' }, // No color specified
|
||||
],
|
||||
};
|
||||
|
||||
const blocks = createLayout(config);
|
||||
|
||||
expect(blocks).toHaveLength(2);
|
||||
// Should default to gray
|
||||
expect(blocks[0].color).toBe('gray');
|
||||
expect(blocks[1].color).toBe('gray');
|
||||
});
|
||||
|
||||
it('should respect explicit colors even when autoColor is true', () => {
|
||||
const config: ByteGridConfig = {
|
||||
name: 'Test',
|
||||
size: 16,
|
||||
layout: 16,
|
||||
autoColor: true,
|
||||
fields: [
|
||||
{ offset: '0-3', name: 'Field1', type: 'uint32_t', color: 'pink' }, // Explicit color
|
||||
{ offset: '4-7', name: 'Field2', type: 'uint32_t' }, // Auto-assign
|
||||
{ offset: '8-11', name: 'Field3', type: 'uint32_t', color: 'mint' }, // Explicit color
|
||||
],
|
||||
};
|
||||
|
||||
const blocks = createLayout(config);
|
||||
|
||||
expect(blocks).toHaveLength(3);
|
||||
expect(blocks[0].color).toBe('pink'); // Explicit
|
||||
expect(blocks[1].color).toBe('cyan'); // Auto (fieldIndex=1 -> cyan)
|
||||
expect(blocks[2].color).toBe('mint'); // Explicit
|
||||
});
|
||||
|
||||
it('should use gray for padding/reserved fields regardless of autoColor', () => {
|
||||
const config: ByteGridConfig = {
|
||||
name: 'Test',
|
||||
size: 16,
|
||||
layout: 16,
|
||||
autoColor: true,
|
||||
fields: [
|
||||
{ offset: '0-3', name: 'Field1', type: 'uint32_t' }, // Auto-assign
|
||||
{ offset: '4-7', name: 'Reserved', type: 'reserved' }, // Should be gray
|
||||
{ offset: '8-11', name: 'Field2', type: 'uint32_t' }, // Auto-assign
|
||||
],
|
||||
};
|
||||
|
||||
const blocks = createLayout(config);
|
||||
|
||||
expect(blocks).toHaveLength(3);
|
||||
expect(blocks[0].color).toBe('blue'); // Auto
|
||||
expect(blocks[1].color).toBe('gray'); // Reserved
|
||||
expect(blocks[2].color).toBe('yellow'); // Auto (fieldIndex=2 -> yellow)
|
||||
});
|
||||
|
||||
it('should cycle through colors for many fields', () => {
|
||||
const config: ByteGridConfig = {
|
||||
name: 'Test',
|
||||
size: 36,
|
||||
layout: 16,
|
||||
autoColor: true,
|
||||
fields: [
|
||||
{ offset: '0-3', name: 'F1', type: 'uint32_t' },
|
||||
{ offset: '4-7', name: 'F2', type: 'uint32_t' },
|
||||
{ offset: '8-11', name: 'F3', type: 'uint32_t' },
|
||||
{ offset: '12-15', name: 'F4', type: 'uint32_t' },
|
||||
{ offset: '16-19', name: 'F5', type: 'uint32_t' },
|
||||
{ offset: '20-23', name: 'F6', type: 'uint32_t' },
|
||||
{ offset: '24-27', name: 'F7', type: 'uint32_t' },
|
||||
{ offset: '28-31', name: 'F8', type: 'uint32_t' },
|
||||
{ offset: '32-35', name: 'F9', type: 'uint32_t' }, // Should cycle back to blue
|
||||
],
|
||||
};
|
||||
|
||||
const blocks = createLayout(config);
|
||||
|
||||
expect(blocks).toHaveLength(9);
|
||||
// First 8 colors
|
||||
expect(blocks[0].color).toBe('blue');
|
||||
expect(blocks[1].color).toBe('cyan');
|
||||
expect(blocks[2].color).toBe('yellow');
|
||||
expect(blocks[3].color).toBe('green');
|
||||
expect(blocks[4].color).toBe('orange');
|
||||
expect(blocks[5].color).toBe('purple');
|
||||
expect(blocks[6].color).toBe('mint');
|
||||
expect(blocks[7].color).toBe('pink');
|
||||
// Cycle back
|
||||
expect(blocks[8].color).toBe('blue');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -740,5 +740,55 @@ fields:
|
|||
expect(result.colorScheme).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
// autoColor tests
|
||||
describe('autoColor', () => {
|
||||
it('should parse autoColor: true', () => {
|
||||
const yaml = `
|
||||
name: Test
|
||||
size: 16
|
||||
autoColor: true
|
||||
fields:
|
||||
- offset: 0-3
|
||||
name: Field1
|
||||
type: uint32_t
|
||||
`;
|
||||
|
||||
const result = parse(yaml);
|
||||
|
||||
expect(result.autoColor).toBe(true);
|
||||
});
|
||||
|
||||
it('should parse autoColor: false', () => {
|
||||
const yaml = `
|
||||
name: Test
|
||||
size: 16
|
||||
autoColor: false
|
||||
fields:
|
||||
- offset: 0-3
|
||||
name: Field1
|
||||
type: uint32_t
|
||||
`;
|
||||
|
||||
const result = parse(yaml);
|
||||
|
||||
expect(result.autoColor).toBe(false);
|
||||
});
|
||||
|
||||
it('should return undefined when autoColor is not specified', () => {
|
||||
const yaml = `
|
||||
name: Test
|
||||
size: 16
|
||||
fields:
|
||||
- offset: 0-3
|
||||
name: Field1
|
||||
type: uint32_t
|
||||
`;
|
||||
|
||||
const result = parse(yaml);
|
||||
|
||||
expect(result.autoColor).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue