Skip to content

Commit 096d9f0

Browse files
authored
fix: ensure ruler 0 is visible (#2487)
* fix: suppress ruler 0 * fix: keep ruler zero label visible without left overflow
1 parent e0982da commit 096d9f0

4 files changed

Lines changed: 51 additions & 29 deletions

File tree

packages/layout-engine/painters/dom/src/ruler/ruler-renderer.test.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,13 @@ describe('createRulerElement', () => {
8888
expect(allTicks[4].style.left).toBe('48px'); // Half tick
8989
});
9090

91-
it('adds labels to main ticks', () => {
91+
it('adds labels to main ticks but skips the leading zero', () => {
9292
const ruler = createRulerElement({ definition, doc });
9393

9494
const labels = ruler.querySelectorAll(`.${RULER_CLASS_NAMES.label}`);
95-
expect(labels.length).toBe(2); // Two main ticks with labels
95+
expect(labels.length).toBe(1); // Label 0 is hidden to prevent overflow clipping
9696

97-
expect(labels[0].textContent).toBe('0');
98-
expect(labels[1].textContent).toBe('1');
97+
expect(labels[0].textContent).toBe('1');
9998
});
10099

101100
it('does not add labels to non-main ticks', () => {
@@ -264,16 +263,16 @@ describe('createRulerElement', () => {
264263
expect(labels.length).toBe(0);
265264
});
266265

267-
it('handles tick with label value of 0', () => {
266+
it('does not render label for tick with label value of 0', () => {
268267
const singleTickDefinition: RulerDefinition = {
269268
...definition,
270269
ticks: [{ size: 'main', height: '20%', label: 0, x: 0 }],
271270
};
272271

273272
const ruler = createRulerElement({ definition: singleTickDefinition, doc });
274273

275-
const label = ruler.querySelector(`.${RULER_CLASS_NAMES.label}`);
276-
expect(label?.textContent).toBe('0');
274+
const labels = ruler.querySelectorAll(`.${RULER_CLASS_NAMES.label}`);
275+
expect(labels.length).toBe(0);
277276
});
278277
});
279278

packages/layout-engine/painters/dom/src/ruler/ruler-renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ function createTickElement(tick: RulerTick, doc: Document): HTMLElement {
155155
`;
156156

157157
// Add label for main ticks
158-
if (tick.label !== undefined) {
158+
if (tick.label !== undefined && tick.label !== 0) {
159159
const label = doc.createElement('span');
160160
label.className = RULER_CLASS_NAMES.label;
161161
label.textContent = String(tick.label);

packages/super-editor/src/components/rulers/Ruler.test.ts

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
1-
/**
2-
* Test suite for Ruler.vue section-awareness
3-
*
4-
* NOTE: The Ruler.vue component currently has a TypeScript syntax error in its
5-
* emit definition (line 6). The correct syntax should be:
6-
*
7-
* const emit = defineEmits(['margin-change']);
8-
*
9-
* instead of:
10-
*
11-
* const emit = defineEmits<{
12-
* 'margin-change': [payload: { side: 'left' | 'right'; value: number; sectionIndex: number }]
13-
* }>();
14-
*
15-
* Once the Ruler.vue file is fixed, these tests can be uncommented and run.
16-
* For now, we document the expected behaviors that should be tested:
17-
*/
18-
191
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2+
import { mount } from '@vue/test-utils';
3+
import { nextTick } from 'vue';
4+
import Ruler from './Ruler.vue';
5+
6+
const createMockEditor = (overrides = {}) => ({
7+
options: { mode: 'docx' },
8+
getPageStyles: vi.fn(() => ({
9+
pageSize: { width: 8.5, height: 11 },
10+
pageMargins: { left: 1, right: 1, top: 1, bottom: 1 },
11+
})),
12+
on: vi.fn(),
13+
off: vi.fn(),
14+
...overrides,
15+
});
2016

2117
/**
2218
* Helper to create a mock emitter for testing event handling
@@ -38,9 +34,30 @@ const createEmitter = () => {
3834
};
3935
};
4036

41-
describe('Ruler.vue section-awareness (blocked by syntax error in Ruler.vue)', () => {
37+
describe('Ruler.vue rendering', () => {
38+
it('renders the leading zero label and keeps it inside the ruler bounds', async () => {
39+
const wrapper = mount(Ruler, {
40+
props: {
41+
editor: createMockEditor(),
42+
},
43+
});
44+
45+
await nextTick();
46+
47+
const labels = wrapper.findAll('.numbering');
48+
expect(labels.length).toBeGreaterThan(1);
49+
expect(labels[0].text()).toBe('0');
50+
expect(labels[0].classes()).toContain('numbering--edge-start');
51+
expect(labels[1].text()).toBe('1');
52+
expect(labels[1].classes()).not.toContain('numbering--edge-start');
53+
54+
wrapper.unmount();
55+
});
56+
});
57+
58+
describe('Ruler.vue section-awareness coverage gaps', () => {
4259
/**
43-
* Required test cases once Ruler.vue syntax is fixed:
60+
* Remaining component test cases to add:
4461
*
4562
* 1. Updates ruler when section changes
4663
* - On 'selectionUpdate' event, should call getCurrentSectionPageStyles()

packages/super-editor/src/components/rulers/Ruler.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,9 @@ onUnmounted(() => {
459459
:class="['ruler-tick', `ruler-tick--${tick.size}`]"
460460
:style="getTickStyle(tick)"
461461
>
462-
<span v-if="tick.label !== undefined" class="numbering">{{ tick.label }}</span>
462+
<span v-if="tick.label !== undefined" :class="['numbering', { 'numbering--edge-start': tick.x === 0 }]">
463+
{{ tick.label }}
464+
</span>
463465
</div>
464466
</template>
465467
</div>
@@ -531,4 +533,8 @@ onUnmounted(() => {
531533
pointer-events: none;
532534
user-select: none;
533535
}
536+
537+
.numbering--edge-start {
538+
left: 0;
539+
}
534540
</style>

0 commit comments

Comments
 (0)