فهرست منبع

annotate parser

Evan You 10 سال پیش
والد
کامیت
68e8c39db9

+ 1 - 0
.flowconfig

@@ -16,3 +16,4 @@ module.name_mapper='^core/\(.*\)$' -> '<PROJECT_ROOT>/src/core/\1'
 module.name_mapper='^shared/\(.*\)$' -> '<PROJECT_ROOT>/src/shared/\1'
 module.name_mapper='^web/\(.*\)$' -> '<PROJECT_ROOT>/src/platforms/web/\1'
 module.name_mapper='^server/\(.*\)$' -> '<PROJECT_ROOT>/src/server/\1'
+module.name_mapper='^entities$' -> '<PROJECT_ROOT>/src/compiler/parser/entity-decoder'

+ 61 - 0
flow/compiler.js

@@ -0,0 +1,61 @@
+declare type CompilerOptions = {
+  warn?: Function,
+  expectHTML?: boolean,
+  directives?: Array<Function>,
+  isUnaryTag?: (tag: string) => ?boolean,
+  isReservedTag?: (tag: string) => ?boolean,
+  mustUseProp?: (attr: string) => ?boolean,
+  getTagNamespace?: (tag: string) => ?string,
+  delimiters?: [string, string]
+}
+
+declare type ASTText = {
+  text: string
+}
+
+declare type ASTExpression = {
+  expression: string,
+  text?: string
+}
+
+declare type ASTElement = {
+  tag: string,
+  attrsList: Array<{ name: string, value: string }>,
+  attrsMap: { [key: string]: string },
+  parent: ASTElement | void,
+  children: Array<ASTElement | ASTText | ASTExpression>,
+
+  text?: string,
+  attrs?: Array<{ name: string, value: string }>,
+  plain?: boolean,
+  pre?: true,
+  ns?: string,
+
+  component?: string,
+  inlineTemplate?: true,
+  slotName?: string,
+  slotTarget?: string,
+
+  render?: true,
+  renderMethod?: string,
+  renderArgs?: string,
+
+  if?: string,
+  else?: true,
+  elseBlock?: ASTElement,
+
+  for?: string,
+  key?: string,
+  alias?: string,
+  iterator?: string,
+
+  staticClass?: string,
+  classBinding?: string,
+  styleBinding?: string,
+
+  transition?: string | true,
+  transitionOnAppear?: boolean,
+
+  forbidden?: true,
+  once?: true
+}

+ 9 - 10
src/compiler/index.js

@@ -1,20 +1,19 @@
+/* @flow */
+
 import { parse } from './parser/index'
 import { optimize } from './optimizer'
 import { generate } from './codegen'
 
 /**
  * Compile a template.
- *
- * @param {String} template
- * @param {Object} options
- *                 - warn
- *                 - directives
- *                 - isReservedTag
- *                 - mustUseProp
- *                 - getTagNamespace
- *                 - delimiters
  */
-export function compile (template, options) {
+export function compile (
+  template: string,
+  options: CompilerOptions
+): {
+  render: string,
+  staticRenderFns: Array<string>
+} {
   const ast = parse(template.trim(), options)
   optimize(ast, options)
   return generate(ast, options)

+ 3 - 1
src/compiler/parser/entity-decoder.js

@@ -1,6 +1,8 @@
+/* @flow */
+
 const decoder = document.createElement('div')
 
-export function decodeHTML (html) {
+export function decodeHTML (html: string): string {
   decoder.innerHTML = html
   return decoder.textContent
 }

+ 4 - 2
src/compiler/parser/filter-parser.js

@@ -1,4 +1,6 @@
-export function parseFilters (exp) {
+/* @flow */
+
+export function parseFilters (exp: string): string {
   let inSingle = false
   let inDouble = false
   let curly = 0
@@ -63,7 +65,7 @@ export function parseFilters (exp) {
   return expression
 }
 
-function wrapFilter (exp, filter) {
+function wrapFilter (exp: string, filter: string): string {
   const i = filter.indexOf('(')
   if (i < 0) {
     return `__resolveFilter__("${filter}")(${exp})`

+ 4 - 0
src/compiler/parser/html-parser.js

@@ -1,3 +1,7 @@
+/**
+ * Not type-checking this file because it's mostly vendor code.
+ */
+
 /*!
  * HTML Parser By John Resig (ejohn.org)
  * Modified by Juriy "kangax" Zaytsev

+ 18 - 17
src/compiler/parser/index.js

@@ -1,3 +1,5 @@
+/* @flow */
+
 import { decodeHTML } from 'entities'
 import { parseHTML } from './html-parser'
 import { parseText } from './text-parser'
@@ -32,15 +34,14 @@ let delimiters
 
 /**
  * Convert HTML string to AST.
- *
- * @param {String} template
- * @param {Object} options
- * @return {Object}
  */
-export function parse (template, options) {
+export function parse (
+  template: string,
+  options: CompilerOptions
+): ASTElement | void {
   warn = options.warn || baseWarn
-  platformGetTagNamespace = options.getTagNamespace || (() => null)
-  platformMustUseProp = options.mustUseProp || (() => false)
+  platformGetTagNamespace = options.getTagNamespace || (_ => null)
+  platformMustUseProp = options.mustUseProp || (_ => false)
   delimiters = options.delimiters
   const stack = []
   let root
@@ -61,7 +62,7 @@ export function parse (template, options) {
       }
 
       tag = tag.toLowerCase()
-      const element = {
+      const element: ASTElement = {
         tag,
         attrsList: attrs,
         attrsMap: makeAttrsMap(attrs),
@@ -133,7 +134,7 @@ export function parse (template, options) {
       }
     },
 
-    end (tag) {
+    end () {
       // remove trailing whitespace
       const element = stack[stack.length - 1]
       const lastNode = element.children[element.children.length - 1]
@@ -147,7 +148,7 @@ export function parse (template, options) {
       }
     },
 
-    chars (text) {
+    chars (text: string) {
       if (!currentParent) {
         if (process.env.NODE_ENV !== 'production' && !warned) {
           warned = true
@@ -162,7 +163,7 @@ export function parse (template, options) {
         // only preserve whitespace if its not right after a starting tag
         : options.preserveWhitespace && currentParent.children.length
           ? ' '
-          : null
+          : ''
       if (text) {
         let expression
         if (!inPre && text !== ' ' && (expression = parseText(text, delimiters))) {
@@ -185,9 +186,9 @@ function processPre (el) {
 function processRawAttrs (el) {
   const l = el.attrsList.length
   if (l) {
-    el.attrs = new Array(l)
+    const attrs = el.attrs = new Array(l)
     for (let i = 0; i < l; i++) {
-      el.attrs[i] = {
+      attrs[i] = {
         name: el.attrsList[i].name,
         value: JSON.stringify(el.attrsList[i].value)
       }
@@ -371,7 +372,7 @@ function processAttrs (el) {
   }
 }
 
-function parseModifiers (name) {
+function parseModifiers (name: string): Object | void {
   const match = name.match(modifierRE)
   if (match) {
     const ret = {}
@@ -380,7 +381,7 @@ function parseModifiers (name) {
   }
 }
 
-function makeAttrsMap (attrs) {
+function makeAttrsMap (attrs: Array<Object>): { [key: string]: string } {
   const map = {}
   for (let i = 0, l = attrs.length; i < l; i++) {
     if (process.env.NODE_ENV !== 'production' && map[attrs[i].name]) {
@@ -391,14 +392,14 @@ function makeAttrsMap (attrs) {
   return map
 }
 
-function findPrevElement (children) {
+function findPrevElement (children: Array<any>): ASTElement | void {
   let i = children.length
   while (i--) {
     if (children[i].tag) return children[i]
   }
 }
 
-function isForbiddenTag (el) {
+function isForbiddenTag (el): boolean {
   return (
     el.tag === 'style' ||
     (el.tag === 'script' && (

+ 7 - 2
src/compiler/parser/text-parser.js

@@ -1,3 +1,5 @@
+/* @flow */
+
 import { cached } from 'shared/util'
 import { parseFilters } from './filter-parser'
 
@@ -10,10 +12,13 @@ const buildRegex = cached(delimiters => {
   return new RegExp(open + '((?:.|\\n)+?)' + close, 'g')
 })
 
-export function parseText (text, delimiters) {
+export function parseText (
+  text: string,
+  delimiters?: [string, string]
+): string | void {
   const tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE
   if (!tagRE.test(text)) {
-    return null
+    return
   }
   const tokens = []
   let lastIndex = tagRE.lastIndex = 0