@mpxjs/webpack-plugin 2.6.113 → 2.6.114-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/lib/config.js +14 -0
  2. package/lib/dependency/AddEntryDependency.js +24 -0
  3. package/lib/dependency/ResolveDependency.js +4 -0
  4. package/lib/index.js +44 -3
  5. package/lib/json-compiler/index.js +3 -0
  6. package/lib/loader.js +43 -2
  7. package/lib/path-loader.js +4 -1
  8. package/lib/platform/template/wx/component-config/button.js +14 -2
  9. package/lib/platform/template/wx/component-config/image.js +4 -0
  10. package/lib/platform/template/wx/component-config/input.js +4 -0
  11. package/lib/platform/template/wx/component-config/rich-text.js +4 -0
  12. package/lib/platform/template/wx/component-config/scroll-view.js +4 -0
  13. package/lib/platform/template/wx/component-config/switch.js +4 -0
  14. package/lib/platform/template/wx/component-config/text.js +4 -0
  15. package/lib/platform/template/wx/component-config/textarea.js +5 -0
  16. package/lib/platform/template/wx/component-config/view.js +4 -0
  17. package/lib/platform/template/wx/index.js +114 -1
  18. package/lib/runtime/components/tenon/filterTag.js +402 -0
  19. package/lib/runtime/components/tenon/getInnerListeners.js +292 -0
  20. package/lib/runtime/components/tenon/tenon-button.vue +305 -0
  21. package/lib/runtime/components/tenon/tenon-image.vue +61 -0
  22. package/lib/runtime/components/tenon/tenon-input.vue +95 -0
  23. package/lib/runtime/components/tenon/tenon-rich-text.vue +30 -0
  24. package/lib/runtime/components/tenon/tenon-scroll-view.vue +118 -0
  25. package/lib/runtime/components/tenon/tenon-switch.vue +91 -0
  26. package/lib/runtime/components/tenon/tenon-text-area.vue +64 -0
  27. package/lib/runtime/components/tenon/tenon-text.vue +64 -0
  28. package/lib/runtime/components/tenon/tenon-view.vue +89 -0
  29. package/lib/runtime/components/tenon/util.js +44 -0
  30. package/lib/runtime/optionProcessor.tenon.js +386 -0
  31. package/lib/template-compiler/compiler.js +11 -2
  32. package/lib/template-compiler/trans-dynamic-class-expr.js +1 -1
  33. package/lib/tenon/index.js +108 -0
  34. package/lib/tenon/processJSON.js +361 -0
  35. package/lib/tenon/processScript.js +260 -0
  36. package/lib/tenon/processStyles.js +21 -0
  37. package/lib/tenon/processTemplate.js +133 -0
  38. package/lib/utils/get-relative-path.js +24 -0
  39. package/package.json +7 -3
@@ -0,0 +1,108 @@
1
+ const processJSON = require('./processJSON')
2
+ const processScript = require('./processScript')
3
+ const processStyles = require('./processStyles')
4
+ const processTemplate = require('./processTemplate')
5
+
6
+ const async = require('async')
7
+
8
+ module.exports = function ({
9
+ mpx,
10
+ loaderContext,
11
+ isProduction,
12
+ parts,
13
+ ctorType,
14
+ filePath,
15
+ queryObj,
16
+ autoScope,
17
+ componentsMap,
18
+ projectRoot,
19
+ getRequireForSrc,
20
+ vueContentCache,
21
+ moduleId,
22
+ callback
23
+ }) {
24
+ const hasComment = parts.template && parts.template.attrs && parts.template.attrs.comments
25
+ const isNative = false
26
+ const mode = mpx.mode
27
+ const srcMode = mpx.srcMode
28
+ const env = mpx.env
29
+ const defs = mpx.defs
30
+ const resolveMode = mpx.resolveMode
31
+ const pagesMap = mpx.pagesMap
32
+
33
+ let output = ''
34
+ let usingComponents = [].concat(Object.keys(mpx.usingComponents))
35
+
36
+ return async.waterfall([
37
+ (callback) => {
38
+ async.parallel([
39
+ (callback) => {
40
+ processTemplate(parts.template, {
41
+ hasComment,
42
+ isNative,
43
+ mode,
44
+ srcMode,
45
+ defs,
46
+ loaderContext,
47
+ moduleId,
48
+ ctorType,
49
+ usingComponents,
50
+ decodeHTMLText: mpx.decodeHTMLText,
51
+ externalClasses: mpx.externalClasses,
52
+ checkUsingComponents: mpx.checkUsingComponents
53
+ }, callback)
54
+ },
55
+ (callback) => {
56
+ processStyles(parts.styles, {
57
+ ctorType,
58
+ autoScope
59
+ }, callback)
60
+ },
61
+ (callback) => {
62
+ processJSON(parts.json, {
63
+ mode,
64
+ env,
65
+ defs,
66
+ resolveMode,
67
+ loaderContext,
68
+ pagesMap,
69
+ pagesEntryMap: mpx.pagesEntryMap,
70
+ pathHash: mpx.pathHash,
71
+ componentsMap,
72
+ projectRoot
73
+ }, callback)
74
+ }
75
+ ], (err, res) => {
76
+ callback(err, res)
77
+ })
78
+ },
79
+ ([templateRes, stylesRes, jsonRes], callback) => {
80
+ output += templateRes.output
81
+ output += stylesRes.output
82
+ output += jsonRes.output
83
+ if (ctorType === 'app' && jsonRes.jsonObj.window && jsonRes.jsonObj.window.navigationBarTitleText) {
84
+ mpx.appTitle = jsonRes.jsonObj.window.navigationBarTitleText
85
+ }
86
+
87
+ processScript(parts.script, {
88
+ ctorType,
89
+ srcMode,
90
+ loaderContext,
91
+ isProduction,
92
+ getRequireForSrc,
93
+ projectRoot,
94
+ jsonConfig: jsonRes.jsonObj,
95
+ componentId: queryObj.componentId || '',
96
+ builtInComponentsMap: templateRes.builtInComponentsMap,
97
+ localComponentsMap: jsonRes.localComponentsMap,
98
+ localPagesMap: jsonRes.localPagesMap,
99
+ forceDisableBuiltInLoader: mpx.forceDisableBuiltInLoader
100
+ }, callback)
101
+ }
102
+ ], (err, scriptRes) => {
103
+ if (err) return callback(err)
104
+ output += scriptRes.output
105
+ vueContentCache.set(filePath, output)
106
+ callback(null, output)
107
+ })
108
+ }
@@ -0,0 +1,361 @@
1
+ const async = require('async')
2
+ const path = require('path')
3
+ const JSON5 = require('json5')
4
+ const loaderUtils = require('loader-utils')
5
+ const parseRequest = require('../utils/parse-request')
6
+ const toPosix = require('../utils/to-posix')
7
+ const addQuery = require('../utils/add-query')
8
+ const parseComponent = require('../parser')
9
+ const readJsonForSrc = require('../utils/read-json-for-src')
10
+ const isUrlRequest = require('../utils/is-url-request')
11
+
12
+ module.exports = function (json, options, rawCallback) {
13
+ const mode = options.mode
14
+ const env = options.env
15
+ const defs = options.defs
16
+ const loaderContext = options.loaderContext
17
+ const resolveMode = options.resolveMode
18
+ const pagesMap = options.pagesMap
19
+ const componentsMap = options.componentsMap
20
+ const pagesEntryMap = options.pagesEntryMap
21
+ const projectRoot = options.projectRoot
22
+ const pathHash = options.pathHash
23
+ const localPagesMap = {}
24
+ const localComponentsMap = {}
25
+ const buildInfo = loaderContext._module.buildInfo
26
+
27
+ let output = '/* json */\n'
28
+ let jsonObj = {}
29
+ let tabBarMap
30
+ let tabBarStr
31
+ const context = loaderContext.context
32
+
33
+ const emitWarning = (msg) => {
34
+ loaderContext.emitWarning(
35
+ new Error('[json processor][' + loaderContext.resource + ']: ' + msg)
36
+ )
37
+ }
38
+
39
+ const emitError = (msg) => {
40
+ this.emitError(
41
+ new Error('[json compiler][' + this.resource + ']: ' + msg)
42
+ )
43
+ }
44
+
45
+ // const stringifyRequest = r => loaderUtils.stringifyRequest(loaderContext, r)
46
+
47
+ const callback = (err) => {
48
+ return rawCallback(err, {
49
+ output,
50
+ jsonObj,
51
+ localPagesMap,
52
+ localComponentsMap,
53
+ tabBarMap,
54
+ tabBarStr
55
+ })
56
+ }
57
+
58
+ if (!json) {
59
+ return callback()
60
+ }
61
+ // 由于json需要提前读取在template处理中使用,src的场景已经在loader中处理了,此处无需考虑json.src的场景
62
+ try {
63
+ jsonObj = JSON5.parse(json.content)
64
+ } catch (e) {
65
+ return callback(e)
66
+ }
67
+
68
+ const fs = loaderContext._compiler.inputFileSystem
69
+
70
+ const resolve = (context, request, callback) => {
71
+ // const { queryObj } = parseRequest(request)
72
+ // todo delete. parseRequest 不会返回 context 属性
73
+ // context = queryObj.context || context
74
+ return loaderContext.resolve(context, request, callback)
75
+ }
76
+
77
+ // const defaultTabbar = {
78
+ // borderStyle: 'black',
79
+ // position: 'bottom',
80
+ // custom: false,
81
+ // isShow: true
82
+ // }
83
+
84
+ // const processTabBar = (tabBar, callback) => {
85
+ // if (tabBar) {
86
+ // tabBar = Object.assign({}, defaultTabbar, tabBar)
87
+ // tabBarMap = {}
88
+ // jsonObj.tabBar.list.forEach(({ pagePath }) => {
89
+ // tabBarMap[pagePath] = true
90
+ // })
91
+ // tabBarStr = JSON.stringify(tabBar)
92
+ // tabBarStr = tabBarStr.replace(/"(iconPath|selectedIconPath)":"([^"]+)"/g, function (matched, $1, $2) {
93
+ // if (isUrlRequest($2, projectRoot)) {
94
+ // return `"${$1}":require(${stringifyRequest(loaderUtils.urlToRequest($2, projectRoot))})`
95
+ // }
96
+ // return matched
97
+ // })
98
+ // }
99
+ // callback()
100
+ // }
101
+
102
+ const processPackages = (packages, context, callback) => {
103
+ if (packages) {
104
+ async.forEach(packages, (packagePath, callback) => {
105
+ const parsed = parseRequest(packagePath)
106
+ const queryObj = parsed.queryObj
107
+ // readFile无法处理query
108
+ packagePath = parsed.resourcePath
109
+ async.waterfall([
110
+ (callback) => {
111
+ resolve(context, packagePath, (err, result) => {
112
+ callback(err, result)
113
+ })
114
+ },
115
+ (result, callback) => {
116
+ loaderContext.addDependency(result)
117
+ fs.readFile(result, (err, content) => {
118
+ if (err) return callback(err)
119
+ callback(err, result, content.toString('utf-8'))
120
+ })
121
+ },
122
+ (result, content, callback) => {
123
+ const filePath = result
124
+ const extName = path.extname(filePath)
125
+ if (extName === '.mpx' || extName === '.vue') {
126
+ const parts = parseComponent(content, {
127
+ filePath,
128
+ needMap: loaderContext.sourceMap,
129
+ mode,
130
+ defs,
131
+ env
132
+ })
133
+ const json = parts.json || {}
134
+ if (json.content) {
135
+ content = json.content
136
+ } else if (json.src) {
137
+ return readJsonForSrc(json.src, loaderContext, (content) => {
138
+ callback(null, result, content)
139
+ })
140
+ }
141
+ }
142
+ callback(null, result, content)
143
+ },
144
+ (result, content, callback) => {
145
+ try {
146
+ content = JSON5.parse(content)
147
+ } catch (err) {
148
+ return callback(err)
149
+ }
150
+
151
+ const processSelfQueue = []
152
+ const context = path.dirname(result)
153
+
154
+ if (content.pages) {
155
+ let tarRoot = queryObj.root
156
+ if (tarRoot) {
157
+ delete queryObj.root
158
+ let subPackage = {
159
+ tarRoot,
160
+ pages: content.pages,
161
+ ...queryObj
162
+ }
163
+ processSelfQueue.push((callback) => {
164
+ processSubPackage(subPackage, context, callback)
165
+ })
166
+ } else {
167
+ processSelfQueue.push((callback) => {
168
+ processPages(content.pages, '', '', context, callback)
169
+ })
170
+ }
171
+ }
172
+ if (content.packages) {
173
+ processSelfQueue.push((callback) => {
174
+ processPackages(content.packages, context, callback)
175
+ })
176
+ }
177
+ if (processSelfQueue.length) {
178
+ async.parallel(processSelfQueue, callback)
179
+ } else {
180
+ callback()
181
+ }
182
+ }
183
+ ], callback)
184
+ }, callback)
185
+ } else {
186
+ callback()
187
+ }
188
+ }
189
+
190
+ const getPageName = (resourcePath, ext) => {
191
+ const baseName = path.basename(resourcePath, ext)
192
+ return path.join('pages', baseName + pathHash(resourcePath), baseName)
193
+ }
194
+
195
+ const processPages = (pages, srcRoot = '', tarRoot = '', context, callback) => {
196
+ if (pages) {
197
+ context = path.join(context, srcRoot)
198
+ async.forEach(pages, (page, callback) => {
199
+ let aliasPath = ''
200
+ if (typeof page !== 'string') {
201
+ aliasPath = page.path
202
+ page = page.src
203
+ }
204
+ if (!isUrlRequest(page, projectRoot)) return callback()
205
+ if (resolveMode === 'native') {
206
+ page = loaderUtils.urlToRequest(page, projectRoot)
207
+ }
208
+ resolve(context, page, (err, resource) => {
209
+ if (err) return callback(err)
210
+ const { resourcePath, queryObj } = parseRequest(resource)
211
+ const ext = path.extname(resourcePath)
212
+ // 获取pageName
213
+ let pageName
214
+ if (aliasPath) {
215
+ pageName = toPosix(path.join(tarRoot, aliasPath))
216
+ // 判断 key 存在重复情况直接报错
217
+ for (let key in pagesMap) {
218
+ if (pagesMap[key] === pageName && key !== resourcePath) {
219
+ emitError(`Current page [${resourcePath}] registers a conflict page path [${pageName}] with existed page [${key}], which is not allowed, please rename it!`)
220
+ return callback()
221
+ }
222
+ }
223
+ } else {
224
+ const relative = path.relative(context, resourcePath)
225
+ if (/^\./.test(relative)) {
226
+ // 如果当前page不存在于context中,对其进行重命名
227
+ pageName = toPosix(path.join(tarRoot, getPageName(resourcePath, ext)))
228
+ emitWarning(`Current page [${resourcePath}] is not in current pages directory [${context}], the page path will be replaced with [${pageName}], use ?resolve to get the page path and navigate to it!`)
229
+ } else {
230
+ pageName = toPosix(path.join(tarRoot, /^(.*?)(\.[^.]*)?$/.exec(relative)[1]))
231
+ // 如果当前page与已有page存在命名冲突,也进行重命名
232
+ for (let key in pagesMap) {
233
+ // 此处引入pagesEntryMap确保相同entry下路由路径重复注册才报错,不同entry下的路由路径重复则无影响
234
+ if (pagesMap[key] === pageName && key !== resourcePath && pagesEntryMap[key] === loaderContext.resourcePath) {
235
+ const pageNameRaw = pageName
236
+ pageName = toPosix(path.join(tarRoot, getPageName(resourcePath, ext)))
237
+ emitWarning(`Current page [${resourcePath}] is registered with a conflict page path [${pageNameRaw}] which is already existed in system, the page path will be replaced with [${pageName}], use ?resolve to get the page path and navigate to it!`)
238
+ break
239
+ }
240
+ }
241
+ }
242
+ }
243
+ if (pagesMap[resourcePath]) {
244
+ emitWarning(`Current page [${resourcePath}] which is imported from [${loaderContext.resourcePath}] has been registered in pagesMap already, it will be ignored, please check it and remove the redundant page declaration!`)
245
+ return callback()
246
+ }
247
+ buildInfo.pagesMap = buildInfo.pagesMap || {}
248
+ buildInfo.pagesMap[resourcePath] = pagesMap[resourcePath] = pageName
249
+ pagesEntryMap[resourcePath] = loaderContext.resourcePath
250
+ localPagesMap[pageName] = {
251
+ resource: addQuery(resource, { page: true }),
252
+ async: tarRoot || queryObj.async,
253
+ isFirst: queryObj.isFirst
254
+ }
255
+ callback()
256
+ })
257
+ }, callback)
258
+ } else {
259
+ callback()
260
+ }
261
+ }
262
+
263
+ const processSubPackage = (subPackage, context, callback) => {
264
+ if (subPackage) {
265
+ let tarRoot = subPackage.tarRoot || subPackage.root || ''
266
+ let srcRoot = subPackage.srcRoot || subPackage.root || ''
267
+ if (!tarRoot) return callback()
268
+ processPages(subPackage.pages, srcRoot, tarRoot, context, callback)
269
+ } else {
270
+ callback()
271
+ }
272
+ }
273
+
274
+ const processSubPackages = (subPackages, context, callback) => {
275
+ if (subPackages) {
276
+ async.forEach(subPackages, (subPackage, callback) => {
277
+ processSubPackage(subPackage, context, callback)
278
+ }, callback)
279
+ } else {
280
+ callback()
281
+ }
282
+ }
283
+
284
+ const processComponents = (components, context, callback) => {
285
+ if (components) {
286
+ async.forEachOf(components, (component, name, callback) => {
287
+ processComponent(component, name, context, callback)
288
+ }, callback)
289
+ } else {
290
+ callback()
291
+ }
292
+ }
293
+
294
+ const processComponent = (component, name, context, callback) => {
295
+ if (!isUrlRequest(component, projectRoot)) return callback()
296
+
297
+ if (resolveMode === 'native') {
298
+ component = loaderUtils.urlToRequest(component, projectRoot)
299
+ }
300
+
301
+ resolve(context, component, (err, resource) => {
302
+ if (err) return callback(err)
303
+ const { resourcePath, queryObj } = parseRequest(resource)
304
+ const parsed = path.parse(resourcePath)
305
+ const componentId = parsed.name + pathHash(resourcePath)
306
+
307
+ buildInfo.packageName = 'main'
308
+ buildInfo.componentsMap = buildInfo.componentsMap || {}
309
+ buildInfo.componentsMap[resourcePath] = componentsMap[resourcePath] = componentId
310
+
311
+ localComponentsMap[name] = {
312
+ resource: addQuery(resource, { component: true, componentId }),
313
+ async: queryObj.async
314
+ }
315
+ callback()
316
+ })
317
+ }
318
+
319
+ // const processGenerics = (generics, context, callback) => {
320
+ // if (generics) {
321
+ // async.forEachOf(generics, (generic, name, callback) => {
322
+ // if (generic.default) {
323
+ // processComponent(generic.default, `${name}default`, context, callback)
324
+ // } else {
325
+ // callback()
326
+ // }
327
+ // }, callback)
328
+ // } else {
329
+ // callback()
330
+ // }
331
+ // }
332
+
333
+ async.parallel([
334
+ (callback) => {
335
+ if (jsonObj.pages && jsonObj.pages[0]) {
336
+ // 标记首页
337
+ if (typeof jsonObj.pages[0] !== 'string') {
338
+ jsonObj.pages[0].src = addQuery(jsonObj.pages[0].src, { isFirst: true })
339
+ } else {
340
+ jsonObj.pages[0] = addQuery(jsonObj.pages[0], { isFirst: true })
341
+ }
342
+ }
343
+ processPages(jsonObj.pages, '', '', context, callback)
344
+ },
345
+ (callback) => {
346
+ processComponents(jsonObj.usingComponents, context, callback)
347
+ },
348
+ (callback) => {
349
+ processPackages(jsonObj.packages, context, callback)
350
+ },
351
+ (callback) => {
352
+ processSubPackages(jsonObj.subPackages || jsonObj.subpackages, context, callback)
353
+ }
354
+ // (callback) => {
355
+ // processGenerics(jsonObj.componentGenerics, context, callback)
356
+ // },
357
+ // (callback) => {
358
+ // processTabBar(jsonObj.tabBar, callback)
359
+ // }
360
+ ], callback)
361
+ }