ui.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. module.exports = api => {
  2. const CONFIG = 'org.vue.pwa'
  3. // Config file
  4. api.describeConfig({
  5. id: CONFIG,
  6. name: 'PWA',
  7. description: 'org.vue.pwa.config.pwa.description',
  8. link: 'https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa#configuration',
  9. files: {
  10. vue: {
  11. js: ['vue.config.js']
  12. },
  13. manifest: {
  14. json: ['public/manifest.json']
  15. }
  16. },
  17. onRead: ({ data }) => {
  18. // Dirty hack here: only in onRead can we delete files from the original data.
  19. // Remove (or, don't create the file) manifest.json if no actual content in it.
  20. if (!data.manifest || !Object.keys(data.manifest).length) {
  21. delete data.manifest
  22. }
  23. return {
  24. prompts: [
  25. {
  26. name: 'workboxPluginMode',
  27. type: 'list',
  28. message: 'org.vue.pwa.config.pwa.workboxPluginMode.message',
  29. description: 'org.vue.pwa.config.pwa.workboxPluginMode.description',
  30. link: 'https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin#which_plugin_to_use',
  31. default: 'GenerateSW',
  32. value: data.vue && data.vue.pwa && data.vue.pwa.workboxPluginMode,
  33. choices: [
  34. {
  35. name: 'GenerateSW',
  36. value: 'GenerateSW'
  37. },
  38. {
  39. name: 'InjectManifest',
  40. value: 'InjectManifest'
  41. }
  42. ]
  43. },
  44. {
  45. name: 'name',
  46. type: 'input',
  47. message: 'org.vue.pwa.config.pwa.name.message',
  48. description: 'org.vue.pwa.config.pwa.name.description',
  49. value: data.vue && data.vue.pwa && data.vue.pwa.name
  50. },
  51. {
  52. name: 'themeColor',
  53. type: 'color',
  54. message: 'org.vue.pwa.config.pwa.themeColor.message',
  55. description: 'org.vue.pwa.config.pwa.themeColor.description',
  56. default: '#4DBA87',
  57. value: data.vue && data.vue.pwa && data.vue.pwa.themeColor
  58. },
  59. {
  60. name: 'backgroundColor',
  61. type: 'color',
  62. message: 'org.vue.pwa.config.pwa.backgroundColor.message',
  63. description: 'org.vue.pwa.config.pwa.backgroundColor.description',
  64. default: '#000000',
  65. value:
  66. (data.vue &&
  67. data.vue.pwa &&
  68. data.vue.pwa.manifestOptions &&
  69. data.vue.pwa.manifestOptions.background_color) ||
  70. (data.manifest && data.manifest.background_color),
  71. skipSave: true
  72. },
  73. {
  74. name: 'msTileColor',
  75. type: 'color',
  76. message: 'org.vue.pwa.config.pwa.msTileColor.message',
  77. description: 'org.vue.pwa.config.pwa.msTileColor.description',
  78. default: '#000000',
  79. value: data.vue && data.vue.pwa && data.vue.pwa.msTileColor
  80. },
  81. {
  82. name: 'appleMobileWebAppStatusBarStyle',
  83. type: 'input',
  84. message: 'org.vue.pwa.config.pwa.appleMobileWebAppStatusBarStyle.message',
  85. description: 'org.vue.pwa.config.pwa.appleMobileWebAppStatusBarStyle.description',
  86. default: 'default',
  87. value: data.vue && data.vue.pwa && data.vue.pwa.appleMobileWebAppStatusBarStyle
  88. },
  89. {
  90. name: 'manifestCrossorigin',
  91. type: 'list',
  92. message: 'org.vue.pwa.config.pwa.manifestCrossorigin.message',
  93. description: 'org.vue.pwa.config.pwa.manifestCrossorigin.description',
  94. default: null,
  95. value: data.vue && data.vue.pwa && data.vue.pwa.manifestCrossorigin,
  96. choices: [
  97. {
  98. name: 'none',
  99. value: null
  100. },
  101. {
  102. name: 'anonymous',
  103. value: 'anonymous'
  104. },
  105. {
  106. name: 'use-credentials',
  107. value: 'use-credentials'
  108. }
  109. ]
  110. }
  111. ]
  112. }
  113. },
  114. onWrite: async ({ api: onWriteApi, data, prompts }) => {
  115. const result = {}
  116. for (const prompt of prompts.filter(p => !p.raw.skipSave)) {
  117. result[`pwa.${prompt.id}`] = await onWriteApi.getAnswer(prompt.id)
  118. }
  119. const backgroundColor = await onWriteApi.getAnswer('backgroundColor')
  120. if (!data.manifest && backgroundColor) {
  121. result['pwa.manifestOptions.background_color'] = backgroundColor
  122. }
  123. onWriteApi.setData('vue', result)
  124. // Update app manifest (only when there's a manifest.json file,
  125. // otherwise it will be inferred from options in vue.config.js)
  126. if (data.manifest) {
  127. const name = result['name']
  128. if (name) {
  129. onWriteApi.setData('manifest', {
  130. name,
  131. short_name: name
  132. })
  133. }
  134. const themeColor = result['themeColor']
  135. if (themeColor) {
  136. onWriteApi.setData('manifest', {
  137. theme_color: themeColor
  138. })
  139. }
  140. if (backgroundColor) {
  141. onWriteApi.setData('manifest', {
  142. background_color: backgroundColor
  143. })
  144. }
  145. }
  146. }
  147. })
  148. const OPEN_VUE = 'org.vue.pwa.open-vue'
  149. const OPEN_MANIFEST = 'org.vue.pwa.open-manifest'
  150. api.onViewOpen(({ view }) => {
  151. if (view.id !== 'vue-project-configurations') {
  152. removeSuggestions()
  153. }
  154. })
  155. api.onConfigRead(({ config }) => {
  156. if (config.id === CONFIG) {
  157. if (config.foundFiles.vue) {
  158. api.addSuggestion({
  159. id: OPEN_VUE,
  160. type: 'action',
  161. label: 'org.vue.pwa.suggestions.open-vue.label',
  162. handler () {
  163. const file = config.foundFiles.vue.path
  164. const { launch } = require('@vue/cli-shared-utils')
  165. launch(file)
  166. return {
  167. keep: true
  168. }
  169. }
  170. })
  171. } else {
  172. api.removeSuggestion(OPEN_VUE)
  173. }
  174. if (config.foundFiles.manifest) {
  175. api.addSuggestion({
  176. id: OPEN_MANIFEST,
  177. type: 'action',
  178. label: 'org.vue.pwa.suggestions.open-manifest.label',
  179. handler () {
  180. const file = config.foundFiles.manifest.path
  181. const { launch } = require('@vue/cli-shared-utils')
  182. launch(file)
  183. return {
  184. keep: true
  185. }
  186. }
  187. })
  188. } else {
  189. api.removeSuggestion(OPEN_MANIFEST)
  190. }
  191. } else {
  192. removeSuggestions()
  193. }
  194. })
  195. function removeSuggestions () {
  196. [OPEN_VUE, OPEN_MANIFEST].forEach(id => api.removeSuggestion(id))
  197. }
  198. }