Browse Source

forgivingly handle < inside template plain text (fix #4012)

Evan You 9 years ago
parent
commit
e2a361a052
2 changed files with 22 additions and 5 deletions
  1. 13 5
      src/compiler/parser/html-parser.js
  2. 9 0
      test/unit/modules/compiler/parser.spec.js

+ 13 - 5
src/compiler/parser/html-parser.js

@@ -91,7 +91,7 @@ export function parseHTML (html, options) {
     last = html
     // Make sure we're not in a script or style element
     if (!lastTag || !isSpecialTag(lastTag, options.sfc, stack)) {
-      const textEnd = html.indexOf('<')
+      let textEnd = html.indexOf('<')
       if (textEnd === 0) {
         // Comment:
         if (/^<!--/.test(html)) {
@@ -137,16 +137,24 @@ export function parseHTML (html, options) {
         }
       }
 
-      let text
-      if (textEnd >= 0) {
+      let text, rest
+      if (textEnd > 0) {
+        rest = html.slice(textEnd)
+        while (!startTagOpen.test(rest) && !endTag.test(rest)) {
+          // < in plain text, be forgiving and treat it as text
+          textEnd += rest.indexOf('<', 1)
+          rest = html.slice(textEnd)
+        }
         text = html.substring(0, textEnd)
         advance(textEnd)
-      } else {
+      }
+
+      if (textEnd < 0) {
         text = html
         html = ''
       }
 
-      if (options.chars) {
+      if (options.chars && text) {
         options.chars(text)
       }
     } else {

+ 9 - 0
test/unit/modules/compiler/parser.spec.js

@@ -375,4 +375,13 @@ describe('parser', () => {
     expect(code.children[2].type).toBe(3)
     expect(code.children[2].text).toBe('\n  ')
   })
+
+  it('forgivingly handle < in plain text', () => {
+    const options = extend({}, baseOptions)
+    const ast = parse('<p>1 < 2 < 3</p>', options)
+    expect(ast.tag).toBe('p')
+    expect(ast.children.length).toBe(1)
+    expect(ast.children[0].type).toBe(3)
+    expect(ast.children[0].text).toBe('1 < 2 < 3')
+  })
 })