Forráskód Böngészése

feat(types): add types for vue-template-compiler (#7918)

katashin 7 éve
szülő
commit
ced774be6d

+ 4 - 0
packages/vue-template-compiler/package.json

@@ -6,6 +6,7 @@
   "unpkg": "browser.js",
   "jsdelivr": "browser.js",
   "browser": "browser.js",
+  "types": "types/index.d.ts",
   "repository": {
     "type": "git",
     "url": "git+https://github.com/vuejs/vue.git"
@@ -23,5 +24,8 @@
   "dependencies": {
     "he": "^1.1.0",
     "de-indent": "^1.0.2"
+  },
+  "devDependencies": {
+    "vue": "file:../.."
   }
 }

+ 221 - 0
packages/vue-template-compiler/types/index.d.ts

@@ -0,0 +1,221 @@
+import Vue, { VNode } from "vue"
+
+/*
+ * Template compilation options / results
+ */
+interface CompilerOptions {
+  modules?: ModuleOptions[];
+  directives?: Record<string, DirectiveFunction>;
+  preserveWhitespace?: boolean;
+}
+
+interface CompiledResult {
+  ast: ASTElement | undefined;
+  render: string;
+  staticRenderFns: string[];
+  errors: string[];
+  tips: string[];
+}
+
+interface CompiledResultFunctions {
+  render: () => VNode;
+  staticRenderFns: (() => VNode)[];
+}
+
+interface ModuleOptions {
+  preTransformNode: (el: ASTElement) => ASTElement | undefined;
+  transformNode: (el: ASTElement) => ASTElement | undefined;
+  postTransformNode: (el: ASTElement) => void;
+  genData: (el: ASTElement) => string;
+  transformCode?: (el: ASTElement, code: string) => string;
+  staticKeys?: string[];
+}
+
+type DirectiveFunction = (node: ASTElement, directiveMeta: ASTDirective) => void;
+
+/*
+ * AST Types
+ */
+
+/**
+ * - 0: FALSE - whole sub tree un-optimizable
+ * - 1: FULL - whole sub tree optimizable
+ * - 2: SELF - self optimizable but has some un-optimizable children
+ * - 3: CHILDREN - self un-optimizable but have fully optimizable children
+ * - 4: PARTIAL - self un-optimizable with some un-optimizable children
+ */
+export type SSROptimizability = 0 | 1 | 2 | 3 | 4
+
+export interface ASTModifiers {
+  [key: string]: boolean;
+}
+
+export interface ASTIfCondition {
+  exp: string | undefined;
+  block: ASTElement;
+}
+
+export interface ASTElementHandler {
+  value: string;
+  params?: any[];
+  modifiers: ASTModifiers | undefined;
+}
+
+export interface ASTElementHandlers {
+  [key: string]: ASTElementHandler | ASTElementHandler[];
+}
+
+export interface ASTDirective {
+  name: string;
+  rawName: string;
+  value: string;
+  arg: string | undefined;
+  modifiers: ASTModifiers | undefined;
+}
+
+export type ASTNode = ASTElement | ASTText | ASTExpression;
+
+export interface ASTElement {
+  type: 1;
+  tag: string;
+  attrsList: { name: string; value: any }[];
+  attrsMap: Record<string, any>;
+  parent: ASTElement | undefined;
+  children: ASTNode[];
+
+  processed?: true;
+
+  static?: boolean;
+  staticRoot?: boolean;
+  staticInFor?: boolean;
+  staticProcessed?: boolean;
+  hasBindings?: boolean;
+
+  text?: string;
+  attrs?: { name: string; value: any }[];
+  props?: { name: string; value: string }[];
+  plain?: boolean;
+  pre?: true;
+  ns?: string;
+
+  component?: string;
+  inlineTemplate?: true;
+  transitionMode?: string | null;
+  slotName?: string;
+  slotTarget?: string;
+  slotScope?: string;
+  scopedSlots?: Record<string, ASTElement>;
+
+  ref?: string;
+  refInFor?: boolean;
+
+  if?: string;
+  ifProcessed?: boolean;
+  elseif?: string;
+  else?: true;
+  ifConditions?: ASTIfCondition[];
+
+  for?: string;
+  forProcessed?: boolean;
+  key?: string;
+  alias?: string;
+  iterator1?: string;
+  iterator2?: string;
+
+  staticClass?: string;
+  classBinding?: string;
+  staticStyle?: string;
+  styleBinding?: string;
+  events?: ASTElementHandlers;
+  nativeEvents?: ASTElementHandlers;
+
+  transition?: string | true;
+  transitionOnAppear?: boolean;
+
+  model?: {
+    value: string;
+    callback: string;
+    expression: string;
+  };
+
+  directives?: ASTDirective[];
+
+  forbidden?: true;
+  once?: true;
+  onceProcessed?: boolean;
+  wrapData?: (code: string) => string;
+  wrapListeners?: (code: string) => string;
+
+  // 2.4 ssr optimization
+  ssrOptimizability?: SSROptimizability;
+
+  // weex specific
+  appendAsTree?: boolean;
+}
+
+export interface ASTExpression {
+  type: 2;
+  expression: string;
+  text: string;
+  tokens: (string | Record<string, any>)[];
+  static?: boolean;
+  // 2.4 ssr optimization
+  ssrOptimizability?: SSROptimizability;
+}
+
+export interface ASTText {
+  type: 3;
+  text: string;
+  static?: boolean;
+  isComment?: boolean;
+  // 2.4 ssr optimization
+  ssrOptimizability?: SSROptimizability;
+}
+
+/*
+ * SFC parser related types
+ */
+interface SFCParserOptions {
+  pad?: true | 'line' | 'space';
+}
+
+export interface SFCBlock {
+  type: string;
+  content: string;
+  attrs: Record<string, string>;
+  start?: number;
+  end?: number;
+  lang?: string;
+  src?: string;
+  scoped?: boolean;
+  module?: string | boolean;
+}
+
+export interface SFCDescriptor {
+  template: SFCBlock | undefined;
+  script: SFCBlock | undefined;
+  styles: SFCBlock[];
+  customBlocks: SFCBlock[];
+}
+
+/*
+ * Exposed functions
+ */
+export function compile(
+  template: string,
+  options?: CompilerOptions
+): CompiledResult;
+
+export function compileToFunctions(template: string): CompiledResultFunctions;
+
+export function ssrCompile(
+  template: string,
+  options?: CompilerOptions
+): CompiledResult;
+
+export function ssrCompileToFunctions(template: string): CompiledResultFunctions;
+
+export function parseComponent(
+  file: string,
+  options?: SFCParserOptions
+): SFCDescriptor;

+ 60 - 0
packages/vue-template-compiler/types/test.ts

@@ -0,0 +1,60 @@
+import Vue, { VNode } from "vue";
+import {
+  compile,
+  compileToFunctions,
+  ssrCompile,
+  ssrCompileToFunctions,
+  parseComponent
+} from "./";
+
+// check compile options
+const compiled = compile("<div>hi</div>", {
+  preserveWhitespace: false,
+  modules: [
+    {
+      preTransformNode: el => el,
+      transformNode: el => el,
+      postTransformNode: el => {
+        el.tag = "p";
+      },
+      genData: el => el.tag,
+      transformCode: (el, code) => code,
+      staticKeys: ["test"]
+    }
+  ],
+  directives: {
+    test: (node, directiveMeta) => {
+      node.tag;
+      directiveMeta.value;
+    }
+  }
+});
+
+// can be passed to function constructor
+new Function(compiled.render);
+compiled.staticRenderFns.map(fn => new Function(fn));
+
+const compiledFns = compileToFunctions("<div>hi</div>");
+
+// can be passed to component render / staticRenderFns options
+const vm = new Vue({
+  data() {
+    return {
+      test: "Test"
+    };
+  },
+  render: compiledFns.render,
+  staticRenderFns: compiledFns.staticRenderFns
+});
+
+// can be called with component instance
+const vnode: VNode = compiledFns.render.call(vm);
+
+// check SFC parser
+const desc = parseComponent("<template></template>", {
+  pad: "space"
+});
+
+const templateContent: string = desc.template!.content;
+const scriptContent: string = desc.script!.content;
+const styleContent: string = desc.styles.map(s => s.content).join("\n");

+ 13 - 0
packages/vue-template-compiler/types/tsconfig.json

@@ -0,0 +1,13 @@
+{
+  "compilerOptions": {
+    "target": "es5",
+    "module": "commonjs",
+    "moduleResolution": "node",
+    "strict": true,
+    "noEmit": true
+  },
+  "compileOnSave": false,
+  "include": [
+    "**/*.ts"
+  ]
+}