/**
* Not type-checking this file because it's mostly vendor code.
*/ /*!
* HTML Parser By John Resig (ejohn.org)
* Modified by Juriy "kangax" Zaytsev
* Original code by Erik Arvidsson, Mozilla Public License
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
*/ import { makeMap, no } from 'shared/util'
import { isNonPhrasingTag, canBeLeftOpenTag } from 'web/util/index' // Regular Expressions for parsing tags and attributes
const singleAttrIdentifier = /([^\s"'<>/=]+)/
const singleAttrAssign = /(?:=)/
const singleAttrValues = [
// attr value double quotes
/"([^"]*)"+/.source,
// attr value, single quotes
/'([^']*)'+/.source,
// attr value, no quotes
/([^\s"'=<>`]+)/.source
]
const attribute = new RegExp(
'^\\s*' + singleAttrIdentifier.source +
'(?:\\s*(' + singleAttrAssign.source + ')' +
'\\s*(?:' + singleAttrValues.join('|') + '))?'
) // could use https://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-QName
// but for Vue templates we can enforce a simple charset
const ncname = '[a-zA-Z_][\\w\\-\\.]*'
const qnameCapture = '((?:' + ncname + '\\:)?' + ncname + ')'
const startTagOpen = new RegExp('^<' + qnameCapture)
const startTagClose = /^\s*(\/?)>/
const endTag = new RegExp('^<\\/' + qnameCapture + '[^>]*>')
const doctype = /^<!DOCTYPE [^>]+>/i
const comment = /^<!--/
const conditionalComment = /^<!\[/ let IS_REGEX_CAPTURING_BROKEN = false
'x'.replace(/x(.)?/g, function (m, g) {
IS_REGEX_CAPTURING_BROKEN = g === ''
}) // Special Elements (can contain anything)
const isScriptOrStyle = makeMap('script,style', true)
const hasLang = attr => attr.name === 'lang' && attr.value !== 'html'
const isSpecialTag = (tag, isSFC, stack) => {
if (isScriptOrStyle(tag)) {
return true
}
if (isSFC && stack.length === 1) {
// top-level template that has no pre-processor
if (tag === 'template' && !stack[0].attrs.some(hasLang)) {
return false
} else {
return true
}
}
return false
} const reCache = {} const ltRE = /&lt;/g
const gtRE = /&gt;/g
const nlRE = / /g
const ampRE = /&amp;/g
const quoteRE = /&quot;/g function decodeAttr (value, shouldDecodeNewlines) {
if (shouldDecodeNewlines) {
value = value.replace(nlRE, '\n')
}
return value
.replace(ltRE, '<')
.replace(gtRE, '>')
.replace(ampRE, '&')
.replace(quoteRE, '"')
} export function parseHTML (html, options) {
const stack = []
const expectHTML = options.expectHTML
const isUnaryTag = options.isUnaryTag || no
let index = 0
let last, lastTag
while (html) {
last = html
// Make sure we're not in a script or style element
if (!lastTag || !isSpecialTag(lastTag, options.sfc, stack)) {
let textEnd = html.indexOf('<')
if (textEnd === 0) {
// Comment:
if (comment.test(html)) {
const commentEnd = html.indexOf('-->') if (commentEnd >= 0) {
advance(commentEnd + 3)
continue
}
} // http://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment
if (conditionalComment.test(html)) {
const conditionalEnd = html.indexOf(']>') if (conditionalEnd >= 0) {
advance(conditionalEnd + 2)
continue
}
} // Doctype:
const doctypeMatch = html.match(doctype)
if (doctypeMatch) {
advance(doctypeMatch[0].length)
continue
} // End tag:
const endTagMatch = html.match(endTag)
if (endTagMatch) {
const curIndex = index
advance(endTagMatch[0].length)
parseEndTag(endTagMatch[0], endTagMatch[1], curIndex, index)
continue
} // Start tag:
const startTagMatch = parseStartTag()
if (startTagMatch) {
handleStartTag(startTagMatch)
continue
}
} let text, rest, next
if (textEnd > 0) {
rest = html.slice(textEnd)
while (
!endTag.test(rest) &&
!startTagOpen.test(rest) &&
!comment.test(rest) &&
!conditionalComment.test(rest)
) {
// < in plain text, be forgiving and treat it as text
next = rest.indexOf('<', 1)
if (next < 0) break
textEnd += next
rest = html.slice(textEnd)
}
text = html.substring(0, textEnd)
advance(textEnd)
} if (textEnd < 0) {
text = html
html = ''
} if (options.chars && text) {
options.chars(text)
}
} else {
var stackedTag = lastTag.toLowerCase()
var reStackedTag = reCache[stackedTag] || (reCache[stackedTag] = new RegExp('([\\s\\S]*?)(</' + stackedTag + '[^>]*>)', 'i'))
var endTagLength = 0
var rest = html.replace(reStackedTag, function (all, text, endTag) {
endTagLength = endTag.length
if (stackedTag !== 'script' && stackedTag !== 'style' && stackedTag !== 'noscript') {
text = text
.replace(/<!--([\s\S]*?)-->/g, '$1')
.replace(/<!\[CDATA\[([\s\S]*?)]]>/g, '$1')
}
if (options.chars) {
options.chars(text)
}
return ''
})
index += html.length - rest.length
html = rest
parseEndTag('</' + stackedTag + '>', stackedTag, index - endTagLength, index)
} if (html === last && options.chars) {
options.chars(html)
break
}
} // Clean up any remaining tags
parseEndTag() function advance (n) {
index += n
html = html.substring(n)
} function parseStartTag () {
const start = html.match(startTagOpen)
if (start) {
const match = {
tagName: start[1],
attrs: [],
start: index
}
advance(start[0].length)
let end, attr
while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {
advance(attr[0].length)
match.attrs.push(attr)
}
if (end) {
match.unarySlash = end[1]
advance(end[0].length)
match.end = index
return match
}
}
} function handleStartTag (match) {
const tagName = match.tagName
let unarySlash = match.unarySlash if (expectHTML) {
if (lastTag === 'p' && isNonPhrasingTag(tagName)) {
parseEndTag('', lastTag)
}
if (canBeLeftOpenTag(tagName) && lastTag === tagName) {
parseEndTag('', tagName)
}
} const unary = isUnaryTag(tagName) || tagName === 'html' && lastTag === 'head' || !!unarySlash const l = match.attrs.length
const attrs = new Array(l)
for (let i = 0; i < l; i++) {
const args = match.attrs[i]
// hackish work around FF bug https://bugzilla.mozilla.org/show_bug.cgi?id=369778
if (IS_REGEX_CAPTURING_BROKEN && args[0].indexOf('""') === -1) {
if (args[3] === '') { delete args[3] }
if (args[4] === '') { delete args[4] }
if (args[5] === '') { delete args[5] }
}
const value = args[3] || args[4] || args[5] || ''
attrs[i] = {
name: args[1],
value: decodeAttr(
value,
options.shouldDecodeNewlines
)
}
} if (!unary) {
stack.push({ tag: tagName, attrs: attrs })
lastTag = tagName
unarySlash = ''
} if (options.start) {
options.start(tagName, attrs, unary, match.start, match.end)
}
} function parseEndTag (tag, tagName, start, end) {
let pos
if (start == null) start = index
if (end == null) end = index // Find the closest opened tag of the same type
if (tagName) {
const needle = tagName.toLowerCase()
for (pos = stack.length - 1; pos >= 0; pos--) {
if (stack[pos].tag.toLowerCase() === needle) {
break
}
}
} else {
// If no tag name is provided, clean shop
pos = 0
} if (pos >= 0) {
// Close all the open elements, up the stack
for (let i = stack.length - 1; i >= pos; i--) {
if (options.end) {
options.end(stack[i].tag, start, end)
}
} // Remove the open elements from the stack
stack.length = pos
lastTag = pos && stack[pos - 1].tag
} else if (tagName.toLowerCase() === 'br') {
if (options.start) {
options.start(tagName, [], true, start, end)
}
} else if (tagName.toLowerCase() === 'p') {
if (options.start) {
options.start(tagName, [], false, start, end)
}
if (options.end) {
options.end(tagName, start, end)
}
}
}
}

vue.js 源代码学习笔记 ----- html-parse.js的更多相关文章

  1. vue.js 源代码学习笔记 ----- core scedule.js

    /* @flow */ import type Watcher from './watcher' import config from '../config' import { callHook } ...

  2. vue.js 源代码学习笔记 ----- core array.js

    /* * not type checking this file because flow doesn't play well with * dynamically accessing methods ...

  3. node.js day01学习笔记:认识node.js

    Node.js(JavaScript,everywhere) 1.Node.js 介绍 1.1. 为什么要学习Node.js 企业需求 + 具有服务端开发经验更好 + front-end + back ...

  4. vue.js 源代码学习笔记 ----- 工具方法 lang

    /* @flow */ // Object.freeze 使得这个对象不能增加属性, 修改属性, 这样就保证了这个对象在任何时候都是空的 export const emptyObject = Obje ...

  5. vue.js 源代码学习笔记 ----- 工具方法 env

    /* @flow */ /* globals MutationObserver */ import { noop } from 'shared/util' // can we use __proto_ ...

  6. vue.js 源代码学习笔记 ----- helpers.js

    /* @flow */ import { parseFilters } from './parser/filter-parser' export function baseWarn (msg: str ...

  7. vue.js 源代码学习笔记 ----- 工具方法 share

    /* @flow */ /** * Convert a value to a string that is actually rendered. { .. } [ .. ] 2 => '' */ ...

  8. vue.js 源代码学习笔记 ----- instance render

    /* @flow */ import { warn, nextTick, toNumber, _toString, looseEqual, emptyObject, handleError, loos ...

  9. vue.js 源代码学习笔记 ----- instance event

    /* @flow */ import { updateListeners } from '../vdom/helpers/index' import { toArray, tip, hyphenate ...

随机推荐

  1. centos 目录文件管理 mkdir,rm,touch,误删文件extundelete,cp,mv,cat,more,less ,head,tail,chown,chmod ,umask 第四节课

    centos 目录文件管理 mkdir,rm,touch,误删文件extundelete,cp,mv,cat,more,less ,head,tail,chown,chmod ,umask  第四节课 ...

  2. tp模板基础

    目录简介 创建应用 在项目目录创建入口文件shop/index.php 创建虚拟主机,访问应 路由形式 路由: 系统从URL参数中分析出当前请求的分组.控制器.和操作的过程就是“路由”. Tp框架路由 ...

  3. myeclipse安装jadclipse(反编译工具)

    我是myeclipse5. 的IDE工具.为了能反编译class文件,上网搜索了很多资料,终于找到一下的一段资料: .将jad.exe 复制到myeclipse安装目录的jre/bin目录下, 如:C ...

  4. Underscore-逐行分析

    标签: // Underscore.js 1.8.3// http://underscorejs.org// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud ...

  5. tslib移植中环境变量编辑

    (1)将/usr/local/tslib下的所有文件复制到移植系统文件中/usr/local(2)编辑移植系统中/etc/profile添加触摸屏支持内容:在/etc/profile文件中设置tsli ...

  6. Vue学习笔记之Vue介绍

    vue的作者叫尤雨溪,中国人.自认为很牛逼的人物,也是我的崇拜之神. 关于他本人的认知,希望大家读一下这篇关于他的文章,或许你会对语言,技术,产生浓厚的兴趣.https://mp.weixin.qq. ...

  7. POJ3278_Catch that cow

    一个简单的bfs题. 用结构体的目的在于保存bfs到达此处时走的步数. 不多言,上AC代码: //18:18 #include<iostream> #include<cstdio&g ...

  8. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none 解决方法

    参考:CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none 环境 主系统 OS X,虚拟机,Ubuntu 14.04 64bit. 问题描述 ...

  9. 利用HTML中map标签实现整张图片带有可点击区域的图像映射:

    实现效果说明:一整张背景图片,实现图标区域出现链接,可点击跳转到指定页面. <div class="brand"> <img src="images/b ...

  10. IIS Express 添加MIME映射

    IIS Express没有提供图形化界面来配置MIME类型,但提供了配置MIME类型的命令行工具. IIS Express中添加MIME映射.操作如下: 在DOS窗口下进入IIS Express安装目 ...