index.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import * as Vue from '../../../packages/weex-vue-framework'
  2. import { compile } from '../../../packages/weex-template-compiler'
  3. import WeexRuntime from 'weex-js-runtime'
  4. import styler from 'weex-styler'
  5. const styleRE = /<\s*style\s*\w*>([^(<\/)]*)<\/\s*style\s*>/g
  6. const scriptRE = /<\s*script.*>([^]*)<\/\s*script\s*>/
  7. const templateRE = /<\s*template\s*>([^]*)<\/\s*template\s*>/
  8. console.debug = () => {}
  9. // http://stackoverflow.com/a/35478115
  10. const matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g
  11. export function strToRegExp (str) {
  12. return new RegExp(str.replace(matchOperatorsRe, '\\$&'))
  13. }
  14. function parseStatic (fns) {
  15. return '[' + fns.map(fn => `function () { ${fn} }`).join(',') + ']'
  16. }
  17. export function compileAndStringify (template) {
  18. const { render, staticRenderFns } = compile(template)
  19. return {
  20. render: `function () { ${render} }`,
  21. staticRenderFns: parseStatic(staticRenderFns)
  22. }
  23. }
  24. /**
  25. * Compile *.vue file into js code
  26. * @param {string} source raw text of *.vue file
  27. * @param {string} componentName whether compile to a component
  28. */
  29. export function compileVue (source, componentName) {
  30. return new Promise((resolve, reject) => {
  31. if (!templateRE.test(source)) {
  32. return reject('No Template!')
  33. }
  34. const scriptMatch = scriptRE.exec(source)
  35. const script = scriptMatch ? scriptMatch[1] : ''
  36. const { render, staticRenderFns } = compile(templateRE.exec(source)[1])
  37. const generateCode = styles => (`
  38. var test_case = Object.assign({
  39. style: ${JSON.stringify(styles)},
  40. render: function () { ${render} },
  41. staticRenderFns: ${parseStatic(staticRenderFns)},
  42. }, (function(){
  43. var module = { exports: {} };
  44. ${script};
  45. return module.exports;
  46. })());
  47. ` + (componentName
  48. ? `Vue.component('${componentName}', test_case);\n`
  49. : `test_case.el = 'body';new Vue(test_case);`)
  50. )
  51. let cssText = ''
  52. let styleMatch = null
  53. while ((styleMatch = styleRE.exec(source))) {
  54. cssText += `\n${styleMatch[1]}\n`
  55. }
  56. styler.parse(cssText, (error, result) => {
  57. if (error) {
  58. return reject(error)
  59. }
  60. resolve(generateCode(result.jsonStyle))
  61. })
  62. resolve(generateCode({}))
  63. })
  64. }
  65. function isObject (object) {
  66. return object !== null && typeof object === 'object'
  67. }
  68. function isEmptyObject (object) {
  69. return isObject(object) && Object.keys(object).length < 1
  70. }
  71. function omitUseless (object) {
  72. if (isObject(object)) {
  73. delete object.ref
  74. for (const key in object) {
  75. if (isEmptyObject(object[key]) || object[key] === undefined) {
  76. delete object[key]
  77. }
  78. omitUseless(object[key])
  79. }
  80. }
  81. return object
  82. }
  83. export function getRoot (instance) {
  84. return omitUseless(instance.document.body.toJSON())
  85. }
  86. // Get all binding events in the instance
  87. export function getEvents (instance) {
  88. const events = []
  89. const recordEvent = node => {
  90. if (!node) { return }
  91. if (Array.isArray(node.event)) {
  92. node.event.forEach(type => {
  93. events.push({ ref: node.ref, type })
  94. })
  95. }
  96. if (Array.isArray(node.children)) {
  97. node.children.forEach(recordEvent)
  98. }
  99. }
  100. recordEvent(instance.document.body.toJSON())
  101. return events
  102. }
  103. export function fireEvent (instance, ref, type, event = {}) {
  104. const el = instance.document.getRef(ref)
  105. if (el) {
  106. instance.document.fireEvent(el, type, event = {})
  107. }
  108. }
  109. export function createInstance (id, code, ...args) {
  110. WeexRuntime.config.frameworks = { Vue }
  111. const context = WeexRuntime.init(WeexRuntime.config)
  112. context.registerModules({
  113. timer: ['setTimeout', 'setInterval']
  114. })
  115. const instance = context.createInstance(id, `// { "framework": "Vue" }\n${code}`, ...args)
  116. instance.$refresh = (data) => context.refreshInstance(id, data)
  117. instance.$destroy = () => context.destroyInstance(id)
  118. return instance
  119. }
  120. export function compileAndExecute (template, additional = '') {
  121. return new Promise(resolve => {
  122. const id = String(Date.now() * Math.random())
  123. const { render, staticRenderFns } = compile(template)
  124. const instance = createInstance(id, `
  125. new Vue({
  126. el: '#whatever',
  127. render: function () { ${render} },
  128. staticRenderFns: ${parseStatic(staticRenderFns)},
  129. ${additional}
  130. })
  131. `)
  132. setTimeout(() => resolve(instance), 10)
  133. })
  134. }
  135. export function syncPromise (arr) {
  136. let p = Promise.resolve()
  137. arr.forEach(item => {
  138. p = p.then(item)
  139. })
  140. return p
  141. }
  142. export function checkRefresh (instance, data, checker) {
  143. return () => new Promise(res => {
  144. instance.$refresh(data)
  145. setTimeout(() => {
  146. checker(getRoot(instance))
  147. res()
  148. })
  149. })
  150. }