Skip to content

Commit d12d306

Browse files
authored
Merge branch 'main' into ci/compressed-size
2 parents 4523933 + bfdd189 commit d12d306

File tree

2 files changed

+136
-27
lines changed

2 files changed

+136
-27
lines changed

debug/src/debug.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,13 @@ export function initDebug() {
353353
});
354354
}
355355

356-
if (typeof type === 'string' && (isTableElement(type) || type === 'p')) {
356+
if (
357+
typeof type === 'string' &&
358+
(isTableElement(type) ||
359+
type === 'p' ||
360+
type === 'a' ||
361+
type === 'button')
362+
) {
357363
// Avoid false positives when Preact only partially rendered the
358364
// HTML tree. Whilst we attempt to include the outer DOM in our
359365
// validation, this wouldn't work on the server for
@@ -387,11 +393,10 @@ export function initDebug() {
387393
type === 'tr' &&
388394
domParentName !== 'thead' &&
389395
domParentName !== 'tfoot' &&
390-
domParentName !== 'tbody' &&
391-
domParentName !== 'table'
396+
domParentName !== 'tbody'
392397
) {
393398
console.error(
394-
'Improper nesting of table. Your <tr> should have a <thead/tbody/tfoot/table> parent.' +
399+
'Improper nesting of table. Your <tr> should have a <thead/tbody/tfoot> parent.' +
395400
serializeVNode(vnode) +
396401
`\n\n${getOwnerStack(vnode)}`
397402
);
@@ -421,6 +426,16 @@ export function initDebug() {
421426
`\n\n${getOwnerStack(vnode)}`
422427
);
423428
}
429+
} else if (type === 'a' || type === 'button') {
430+
if (getDomChildren(vnode).indexOf(type) !== -1) {
431+
console.error(
432+
`Improper nesting of interactive content. Your <${type}>` +
433+
` should not have other ${type === 'a' ? 'anchor' : 'button'}` +
434+
' tags as child-elements.' +
435+
serializeVNode(vnode) +
436+
`\n\n${getOwnerStack(vnode)}`
437+
);
438+
}
424439
}
425440
}
426441

debug/test/browser/debug.test.js

Lines changed: 117 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -543,12 +543,14 @@ describe('debug', () => {
543543
it('Accepts minimal well formed table', () => {
544544
const Table = () => (
545545
<table>
546-
<tr>
547-
<th>Head</th>
548-
</tr>
549-
<tr>
550-
<td>Body</td>
551-
</tr>
546+
<tbody>
547+
<tr>
548+
<th>Head</th>
549+
</tr>
550+
<tr>
551+
<td>Body</td>
552+
</tr>
553+
</tbody>
552554
</table>
553555
);
554556
render(<Table />, scratch);
@@ -586,23 +588,27 @@ describe('debug', () => {
586588
it('accepts valid nested tables', () => {
587589
const Table = () => (
588590
<table>
589-
<tr>
590-
<th>foo</th>
591-
</tr>
592-
<tr>
593-
<td id="nested">
594-
<table>
595-
<tr>
596-
<td>cell1</td>
597-
<td>cell2</td>
598-
<td>cell3</td>
599-
</tr>
600-
</table>
601-
</td>
602-
</tr>
603-
<tr>
604-
<td>bar</td>
605-
</tr>
591+
<tbody>
592+
<tr>
593+
<th>foo</th>
594+
</tr>
595+
<tr>
596+
<td id="nested">
597+
<table>
598+
<tbody>
599+
<tr>
600+
<td>cell1</td>
601+
<td>cell2</td>
602+
<td>cell3</td>
603+
</tr>
604+
</tbody>
605+
</table>
606+
</td>
607+
</tr>
608+
<tr>
609+
<td>bar</td>
610+
</tr>
611+
</tbody>
606612
</table>
607613
);
608614

@@ -661,6 +667,94 @@ describe('debug', () => {
661667
});
662668
});
663669

670+
describe('button nesting', () => {
671+
it('should not warn on a regular button', () => {
672+
const Button = () => <button>Hello world</button>;
673+
674+
render(<Button />, scratch);
675+
expect(console.error).to.not.be.called;
676+
});
677+
678+
it('should warn for nesting illegal dom-nodes under a button', () => {
679+
const Button = () => (
680+
<button>
681+
<button>Hello world</button>
682+
</button>
683+
);
684+
685+
render(<Button />, scratch);
686+
expect(console.error).to.be.calledOnce;
687+
});
688+
689+
it('should warn for nesting illegal dom-nodes under a button as func', () => {
690+
const ButtonChild = ({ children }) => <button>{children}</button>;
691+
const Button = () => (
692+
<button>
693+
<ButtonChild>Hello world</ButtonChild>
694+
</button>
695+
);
696+
697+
render(<Button />, scratch);
698+
expect(console.error).to.be.calledOnce;
699+
});
700+
701+
it('should not warn for nesting non-interactive content under a button', () => {
702+
const Button = () => (
703+
<button>
704+
<span>Hello </span>
705+
<a>World</a>
706+
</button>
707+
);
708+
709+
render(<Button />, scratch);
710+
expect(console.error).to.not.be.called;
711+
});
712+
});
713+
714+
describe('anchor nesting', () => {
715+
it('should not warn a regular anchor', () => {
716+
const Anchor = () => <a>Hello world</a>;
717+
718+
render(<Anchor />, scratch);
719+
expect(console.error).to.not.be.called;
720+
});
721+
722+
it('should warn for nesting illegal dom-nodes under an anchor', () => {
723+
const Anchor = () => (
724+
<a>
725+
<a>Hello world</a>
726+
</a>
727+
);
728+
729+
render(<Anchor />, scratch);
730+
expect(console.error).to.be.calledOnce;
731+
});
732+
733+
it('should warn for nesting illegal dom-nodes under an anchor as func', () => {
734+
const AnchorChild = ({ children }) => <a>{children}</a>;
735+
const Anchor = () => (
736+
<a>
737+
<AnchorChild>Hello world</AnchorChild>
738+
</a>
739+
);
740+
741+
render(<Anchor />, scratch);
742+
expect(console.error).to.be.calledOnce;
743+
});
744+
745+
it('should not warn for nesting non-interactive content under an anchor', () => {
746+
const Anchor = () => (
747+
<a>
748+
<span>Hello </span>
749+
<button>World</button>
750+
</a>
751+
);
752+
753+
render(<Anchor />, scratch);
754+
expect(console.error).to.not.be.called;
755+
});
756+
});
757+
664758
describe('PropTypes', () => {
665759
beforeEach(() => {
666760
resetPropWarnings();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy