Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 

270 lignes
8.8 KiB

  1. import { MagicString } from 'vue/compiler-sfc'
  2. import { findNode, parseSFC } from './utils.js'
  3. function getPageRootRefSource(sfc, enabledGlobalRef = false) {
  4. const pageTempAttrs = sfc.template?.attrs
  5. if (pageTempAttrs && pageTempAttrs.root) {
  6. return `ref="${pageTempAttrs.root}"`
  7. }
  8. return enabledGlobalRef ? 'ref="uniUpRoot"' : ''
  9. }
  10. function ensureNvueNavigationBar(pageMetaSource) {
  11. const navigationBarSource = '<navigation-bar :front-color="upThemeNavFrontColor" :background-color="upThemeNavBgColor" />'
  12. if (!pageMetaSource) return `<page-meta>${navigationBarSource}</page-meta>`
  13. if (pageMetaSource.indexOf('navigation-bar') > -1 || pageMetaSource.indexOf('NavigationBar') > -1) {
  14. return pageMetaSource
  15. }
  16. return pageMetaSource.replace(/<page-meta([^>]*)>/i, `<page-meta$1>${navigationBarSource}`)
  17. }
  18. function wrapTemplate(ms, sfc, tagName, rootRefSource = '', withNvueNavigationBar = false) {
  19. const pageTempStart = sfc.template?.loc.start.offset
  20. const pageTempEnd = sfc.template?.loc.end.offset
  21. let pageMetaSource = ''
  22. const pageMetaNode = findNode(sfc, 'PageMeta')
  23. if (pageMetaNode) {
  24. pageMetaSource = pageMetaNode.loc.source
  25. const metaTempStart = pageMetaNode.loc.start.offset
  26. const metaTempEnd = pageMetaNode.loc.end.offset
  27. ms.remove(metaTempStart, metaTempEnd)
  28. }
  29. if (withNvueNavigationBar) {
  30. pageMetaSource = ensureNvueNavigationBar(pageMetaSource)
  31. }
  32. if (pageTempStart != null && pageTempEnd != null) {
  33. ms.appendLeft(pageTempStart, `\n${pageMetaSource}\n<${tagName} ${rootRefSource}>`)
  34. ms.appendRight(pageTempEnd, `\n</${tagName}>\n`)
  35. }
  36. }
  37. export async function transformPage(code, enabledGlobalRef = false) {
  38. const sfc = await parseSFC(code)
  39. const ms = new MagicString(code)
  40. wrapTemplate(ms, sfc, 'global-up-root', getPageRootRefSource(sfc, enabledGlobalRef))
  41. return ms
  42. }
  43. function ensureOptionsComponent(ms, scriptContent) {
  44. if (scriptContent.includes('UpNvueRoot')) return
  45. const componentsMatch = scriptContent.match(/components\s*:\s*\{/)
  46. if (componentsMatch) {
  47. ms.appendLeft(componentsMatch.index + componentsMatch[0].length, ' UpNvueRoot,')
  48. return
  49. }
  50. const exportDefaultMatch = scriptContent.match(/export\s+default\s+(?:defineComponent\s*\()?\s*\{/)
  51. if (exportDefaultMatch) {
  52. ms.appendLeft(
  53. exportDefaultMatch.index + exportDefaultMatch[0].length,
  54. '\n components: { UpNvueRoot },'
  55. )
  56. }
  57. }
  58. function ensureOptionsThemeMixin(ms, scriptContent) {
  59. if (scriptContent.includes('__upNvueThemeMixin')) return
  60. const mixinsMatch = scriptContent.match(/mixins\s*:\s*\[/)
  61. if (mixinsMatch) {
  62. ms.appendLeft(mixinsMatch.index + mixinsMatch[0].length, ' __upNvueThemeMixin,')
  63. return
  64. }
  65. const exportDefaultMatch = scriptContent.match(/export\s+default\s+(?:defineComponent\s*\()?\s*\{/)
  66. if (exportDefaultMatch) {
  67. ms.appendLeft(
  68. exportDefaultMatch.index + exportDefaultMatch[0].length,
  69. '\n mixins: [__upNvueThemeMixin],'
  70. )
  71. }
  72. }
  73. function getScriptSetupImports(componentImportPath, runtimeImportPath) {
  74. return `import UpNvueRoot from '${componentImportPath}'
  75. import { computed as __upComputed, onBeforeUnmount as __upOnBeforeUnmount, onMounted as __upOnMounted, ref as __upRef } from 'vue'
  76. import { onShow as __upOnShow } from '@dcloudio/uni-app'
  77. import {
  78. applyNativeThemeUI as __upApplyNativeThemeUI,
  79. applyNativeThemeUIDeferred as __upApplyNativeThemeUIDeferred,
  80. getThemeCardStyle as __upGetThemeCardStyle,
  81. getThemeIsDark as __upGetThemeIsDark,
  82. getThemePageStyle as __upGetThemePageStyle,
  83. getThemeVar as __upThemeVar,
  84. syncThemeRuntimeFromStorage as __upSyncThemeRuntimeFromStorage
  85. } from '${runtimeImportPath}'
  86. const __upThemeVersion = __upRef(0)
  87. let __upThemeChangeHandler = null
  88. const __upReadThemeVersion = () => Number((typeof uni !== 'undefined' && uni.$u && uni.$u.theme && uni.$u.theme.version) || 0)
  89. const __upSyncThemeVersion = (payload = {}) => {
  90. const version = Number(payload.version || __upReadThemeVersion() || 0)
  91. __upThemeVersion.value = version || Number(__upThemeVersion.value || 0) + 1
  92. }
  93. __upOnMounted(() => {
  94. __upSyncThemeRuntimeFromStorage()
  95. __upSyncThemeVersion()
  96. __upApplyNativeThemeUI()
  97. if (typeof uni !== 'undefined' && typeof uni.$on === 'function') {
  98. __upThemeChangeHandler = (payload = {}) => {
  99. __upSyncThemeRuntimeFromStorage()
  100. __upSyncThemeVersion(payload)
  101. __upApplyNativeThemeUI()
  102. }
  103. uni.$on('uThemeChange', __upThemeChangeHandler)
  104. }
  105. })
  106. __upOnShow(() => {
  107. __upSyncThemeRuntimeFromStorage()
  108. __upSyncThemeVersion()
  109. __upApplyNativeThemeUIDeferred()
  110. })
  111. __upOnBeforeUnmount(() => {
  112. if (typeof uni !== 'undefined' && typeof uni.$off === 'function' && __upThemeChangeHandler) {
  113. uni.$off('uThemeChange', __upThemeChangeHandler)
  114. __upThemeChangeHandler = null
  115. }
  116. })
  117. const upThemeVar = (varName, fallbackColor) => {
  118. __upThemeVersion.value
  119. return __upThemeVar(varName, fallbackColor)
  120. }
  121. const upThemeCardStyle = __upComputed(() => {
  122. __upThemeVersion.value
  123. return __upGetThemeCardStyle()
  124. })
  125. const upThemePageStyle = __upComputed(() => {
  126. __upThemeVersion.value
  127. return __upGetThemePageStyle()
  128. })
  129. const upThemeIsDark = __upComputed(() => {
  130. __upThemeVersion.value
  131. return __upGetThemeIsDark()
  132. })
  133. const upThemeNavFrontColor = __upComputed(() => {
  134. __upThemeVersion.value
  135. return __upGetThemeIsDark() ? '#ffffff' : '#000000'
  136. })
  137. const upThemeNavBgColor = __upComputed(() => {
  138. __upThemeVersion.value
  139. return __upThemeVar('--up-navbar-bg-color', __upGetThemeIsDark() ? '#1c1c1e' : '#ffffff')
  140. })
  141. `
  142. }
  143. function getOptionsImports(componentImportPath, runtimeImportPath) {
  144. return `import UpNvueRoot from '${componentImportPath}'
  145. import {
  146. applyNativeThemeUI as __upApplyNativeThemeUI,
  147. applyNativeThemeUIDeferred as __upApplyNativeThemeUIDeferred,
  148. getThemeCardStyle as __upGetThemeCardStyle,
  149. getThemeIsDark as __upGetThemeIsDark,
  150. getThemePageStyle as __upGetThemePageStyle,
  151. getThemeVar as __upThemeVar,
  152. syncThemeRuntimeFromStorage as __upSyncThemeRuntimeFromStorage
  153. } from '${runtimeImportPath}'
  154. const __upNvueThemeMixin = {
  155. data() {
  156. return {
  157. __upNvueThemeVersion: 0,
  158. __upNvueThemeChangeHandler: null
  159. }
  160. },
  161. created() {
  162. __upSyncThemeRuntimeFromStorage()
  163. this.__upSyncNvueThemeVersion()
  164. __upApplyNativeThemeUI()
  165. if (typeof uni !== 'undefined' && typeof uni.$on === 'function') {
  166. this.__upNvueThemeChangeHandler = (payload = {}) => {
  167. __upSyncThemeRuntimeFromStorage()
  168. this.__upSyncNvueThemeVersion(payload)
  169. __upApplyNativeThemeUI()
  170. }
  171. uni.$on('uThemeChange', this.__upNvueThemeChangeHandler)
  172. }
  173. },
  174. onShow() {
  175. __upSyncThemeRuntimeFromStorage()
  176. this.__upSyncNvueThemeVersion()
  177. __upApplyNativeThemeUIDeferred()
  178. },
  179. beforeUnmount() {
  180. if (typeof uni !== 'undefined' && typeof uni.$off === 'function' && this.__upNvueThemeChangeHandler) {
  181. uni.$off('uThemeChange', this.__upNvueThemeChangeHandler)
  182. this.__upNvueThemeChangeHandler = null
  183. }
  184. },
  185. computed: {
  186. upThemeCardStyle() {
  187. this.__upNvueThemeVersion
  188. return __upGetThemeCardStyle()
  189. },
  190. upThemePageStyle() {
  191. this.__upNvueThemeVersion
  192. return __upGetThemePageStyle()
  193. },
  194. upThemeIsDark() {
  195. this.__upNvueThemeVersion
  196. return __upGetThemeIsDark()
  197. },
  198. upThemeNavFrontColor() {
  199. this.__upNvueThemeVersion
  200. return __upGetThemeIsDark() ? '#ffffff' : '#000000'
  201. },
  202. upThemeNavBgColor() {
  203. this.__upNvueThemeVersion
  204. return __upThemeVar('--up-navbar-bg-color', __upGetThemeIsDark() ? '#1c1c1e' : '#ffffff')
  205. }
  206. },
  207. methods: {
  208. __upReadNvueThemeVersion() {
  209. return Number((typeof uni !== 'undefined' && uni.$u && uni.$u.theme && uni.$u.theme.version) || 0)
  210. },
  211. __upSyncNvueThemeVersion(payload = {}) {
  212. const version = Number(payload.version || this.__upReadNvueThemeVersion() || 0)
  213. this.__upNvueThemeVersion = version || Number(this.__upNvueThemeVersion || 0) + 1
  214. },
  215. upThemeVar(varName, fallbackColor) {
  216. this.__upNvueThemeVersion
  217. return __upThemeVar(varName, fallbackColor)
  218. }
  219. }
  220. }
  221. `
  222. }
  223. export async function transformNvuePage(
  224. code,
  225. componentImportPath,
  226. runtimeImportPath,
  227. enabledGlobalRef = false
  228. ) {
  229. const sfc = await parseSFC(code)
  230. const ms = new MagicString(code)
  231. wrapTemplate(ms, sfc, 'UpNvueRoot', getPageRootRefSource(sfc, enabledGlobalRef), true)
  232. if (sfc.scriptSetup) {
  233. ms.appendLeft(sfc.scriptSetup.loc.start.offset, getScriptSetupImports(componentImportPath, runtimeImportPath))
  234. } else if (sfc.script) {
  235. ms.appendLeft(sfc.script.loc.start.offset, getOptionsImports(componentImportPath, runtimeImportPath))
  236. ensureOptionsComponent(ms, sfc.script.content)
  237. ensureOptionsThemeMixin(ms, sfc.script.content)
  238. } else {
  239. ms.append(
  240. `\n<script>\n${getOptionsImports(componentImportPath, runtimeImportPath)}export default {\n components: { UpNvueRoot },\n mixins: [__upNvueThemeMixin]\n}\n</script>\n`
  241. )
  242. }
  243. return ms
  244. }