File tree Expand file tree Collapse file tree 6 files changed +73
-4
lines changed
app/javascript/components/bootcamp Expand file tree Collapse file tree 6 files changed +73
-4
lines changed Original file line number Diff line number Diff line change @@ -17,6 +17,7 @@ import { runHtmlChecks } from '../checks/runHtmlChecks'
17
17
import { CheckResult } from '../checks/runChecks'
18
18
import { runCssChecks } from '../checks/runCssChecks'
19
19
import { validateHtml5 } from '../../common/validateHtml5/validateHtml5'
20
+ import { normalizeHtmlText } from '../../common/validateHtml5/normalizeHtmlText'
20
21
21
22
export function ControlButtons ( {
22
23
getEditorValues,
@@ -54,7 +55,8 @@ export function ControlButtons({
54
55
let firstFailingCheck : CheckResult | null = null
55
56
56
57
if ( htmlValue . length > 0 ) {
57
- const isHTMLValid = validateHtml5 ( htmlValue )
58
+ const normalizedHtml = normalizeHtmlText ( htmlValue )
59
+ const isHTMLValid = validateHtml5 ( normalizedHtml )
58
60
59
61
if ( ! isHTMLValid . isValid ) {
60
62
toast . error (
Original file line number Diff line number Diff line change @@ -11,12 +11,13 @@ import { useFrontendExercisePageStore } from '../store/frontendExercisePageStore
11
11
import toast from 'react-hot-toast'
12
12
import { wrapJSCode } from './wrapJSCode'
13
13
import { validateHtml5 } from '../../common/validateHtml5/validateHtml5'
14
+ import { normalizeHtmlText } from '../../common/validateHtml5/normalizeHtmlText'
14
15
15
16
export type TabIndex = 'html' | 'css' | 'javascript'
16
17
17
18
export const TabsContext = createContext < TabContext > ( {
18
19
current : 'html' ,
19
- switchToTab : ( ) => { } ,
20
+ switchToTab : ( ) => { } ,
20
21
} )
21
22
22
23
export function LHS ( ) {
@@ -59,7 +60,8 @@ export function LHS() {
59
60
const htmlText = htmlEditorRef . current . state . doc . toString ( )
60
61
61
62
if ( htmlText . length > 0 ) {
62
- const isHTMLValid = validateHtml5 ( htmlText )
63
+ const normalizedHtml = normalizeHtmlText ( htmlText )
64
+ const isHTMLValid = validateHtml5 ( normalizedHtml )
63
65
64
66
if ( ! isHTMLValid . isValid ) {
65
67
setTab ( 'html' )
Original file line number Diff line number Diff line change
1
+ export function normalizeHtmlText ( html : string ) {
2
+ // remove comments
3
+ html = html . replace ( / < ! - - [ \s \S ] * ?- - > / g, '' )
4
+ // remove svg
5
+ html = html . replace ( / < s v g [ \s \S ] * ?< \/ s v g > / g, '' )
6
+
7
+ return html
8
+ }
Original file line number Diff line number Diff line change 1
1
export function checkVoidTagClosure ( html : string ) : void {
2
2
const voidRegex =
3
- / < ( a r e a | b a s e | b r | c o l | e m b e d | h r | i m g | i n p u t | l i n k | m e t a | s o u r c e | t r a c k | w b r ) \b [ ^ < > ] * ?(? ! > ) $ / gim
3
+ / < ( a r e a | b a s e | b r | c o l | e m b e d | h r | i m g | i n p u t | l i n k | m e t a | s o u r c e | t r a c k | w b r | c i r c l e | e l l i p s e | l i n e | p a t h | p o l y g o n | p o l y l i n e | r e c t | s t o p | u s e | i m a g e ) \b [ ^ < > ] * ?(? ! > ) $ / gim
4
4
5
5
const malformedVoidTag = html . match ( voidRegex )
6
6
Original file line number Diff line number Diff line change 1
1
// list of elements that don't require a closing tag
2
2
export const voidElements = new Set ( [
3
+ // HTML void elements
3
4
'area' ,
4
5
'base' ,
5
6
'br' ,
@@ -13,6 +14,17 @@ export const voidElements = new Set([
13
14
'source' ,
14
15
'track' ,
15
16
'wbr' ,
17
+ // svg
18
+ 'circle' ,
19
+ 'ellipse' ,
20
+ 'line' ,
21
+ 'path' ,
22
+ 'polygon' ,
23
+ 'polyline' ,
24
+ 'rect' ,
25
+ 'stop' ,
26
+ 'use' ,
27
+ 'image' ,
16
28
] )
17
29
18
30
export function isVoidElement ( tagName : string ) : boolean {
Original file line number Diff line number Diff line change
1
+ import { normalizeHtmlText } from '../../../app/javascript/components/bootcamp/common/validateHtml5/normalizeHtmlText'
2
+
3
+ describe ( 'normalizeHtmlText' , ( ) => {
4
+ it ( 'removes HTML comments' , ( ) => {
5
+ expect ( normalizeHtmlText ( '<p>Hello</p><!-- comment -->' ) ) . toBe (
6
+ '<p>Hello</p>'
7
+ )
8
+ } )
9
+
10
+ it ( 'removes multiple comments' , ( ) => {
11
+ expect ( normalizeHtmlText ( '<!--A--><div>Content</div><!--B-->' ) ) . toBe (
12
+ '<div>Content</div>'
13
+ )
14
+ } )
15
+
16
+ it ( 'removes SVG block' , ( ) => {
17
+ expect ( normalizeHtmlText ( '<div><svg><circle /></svg></div>' ) ) . toBe (
18
+ '<div></div>'
19
+ )
20
+ } )
21
+
22
+ it ( 'removes multiline SVG and comments' , ( ) => {
23
+ const cleaned = normalizeHtmlText ( `
24
+ <div>
25
+ <!-- Comment -->
26
+ <svg>
27
+ <rect />
28
+ </svg>
29
+ Text
30
+ </div>
31
+ ` )
32
+ expect ( cleaned . replace ( / \s + / g, ' ' ) . trim ( ) ) . toBe ( '<div> Text </div>' )
33
+ } )
34
+
35
+ it ( 'removes multiple SVGs and comments' , ( ) => {
36
+ const result = normalizeHtmlText ( `
37
+ <!-- top -->
38
+ <svg><circle /></svg>
39
+ <p>Hello</p>
40
+ <svg><rect /></svg>
41
+ <!-- bottom -->
42
+ ` )
43
+ expect ( result . replace ( / \s + / g, ' ' ) . trim ( ) ) . toBe ( '<p>Hello</p>' )
44
+ } )
45
+ } )
You can’t perform that action at this time.
0 commit comments