Initial commit
This commit is contained in:
248
wechat-mini-program/node_modules/mp-html/tools/plugin.js
generated
vendored
Normal file
248
wechat-mini-program/node_modules/mp-html/tools/plugin.js
generated
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* @fileoverview 处理插件
|
||||
*/
|
||||
const path = require('path')
|
||||
const through2 = require('through2')
|
||||
|
||||
const config = require('./config')
|
||||
|
||||
config.plugins.sort((a, b) => {
|
||||
// editable 置于最后面
|
||||
if (a === 'editable') return 1
|
||||
if (b === 'editable') return -1
|
||||
// markdown 置于最前面
|
||||
if (a === 'markdown') return -1
|
||||
if (b === 'markdown') return 1
|
||||
// 剩余任意顺序
|
||||
return 0
|
||||
})
|
||||
|
||||
// 提取和替换标签名选择器(组件中仅支持 class 选择器)
|
||||
const tagSelector = {}
|
||||
let tagI = 0
|
||||
if (config.externStyle) {
|
||||
config.externStyle = config.externStyle.replace(/[^,\s}]+(?=[^}]*{)/g, $ => {
|
||||
if (!/[a-zA-Z_]/.test($[0])) return $
|
||||
if (tagSelector[$]) return '.' + tagSelector[$]
|
||||
tagSelector[$] = '_' + tagI++
|
||||
return '.' + tagSelector[$]
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* @description 构建插件
|
||||
* @param {string} platform 使用平台
|
||||
*/
|
||||
build (platform) {
|
||||
const builds = {} // 构建模块
|
||||
let pluginImports = '' // 插件引入
|
||||
let plugins = '' // 插件列表
|
||||
let voidTags = '' // 增加的自闭合标签
|
||||
let wxml = '' // 要引入到 node.wxml 中的内容
|
||||
let js = '' // 要引入到 node.js 中的内容
|
||||
let wxss = config.externStyle // 要引入到 node.wxss 中的内容
|
||||
const json = {} // 要引入到 node.json 中的内容
|
||||
|
||||
// 收集插件中要写入模板文件的内容
|
||||
for (let i = 0; i < config.plugins.length; i++) {
|
||||
const plugin = config.plugins[i]
|
||||
let build = {}
|
||||
try {
|
||||
// 专用 build
|
||||
if (platform === 'uni-app') {
|
||||
build = require(`../plugins/${plugin}/uni-app/build.js`)
|
||||
} else {
|
||||
build = require(`../plugins/${plugin}/miniprogram/build.js`)
|
||||
}
|
||||
} catch (e) { }
|
||||
try {
|
||||
// 通用 build
|
||||
build = Object.assign(require(`../plugins/${plugin}/build.js`), build)
|
||||
} catch (e) { }
|
||||
// 可以在当前平台使用
|
||||
if (!build.platform || build.platform.includes(platform)) {
|
||||
builds[plugin] = build
|
||||
if (platform === 'uni-app') {
|
||||
plugins += plugin.replace(/-([a-z])/g, ($, $1) => $1.toUpperCase()) + ','
|
||||
pluginImports += `import ${plugin.replace(/-([a-z])/g, ($, $1) => $1.toUpperCase())} from './${plugin}/${build.main ? build.main : 'index.js'}'\n`
|
||||
} else {
|
||||
plugins += `require('./${plugin}/${build.main ? build.main : 'index.js'}'),`
|
||||
}
|
||||
if (build.template) {
|
||||
wxml += build.template.replace('wx:if', 'wx:elif').replace('v-if', 'v-else-if')
|
||||
}
|
||||
if (build.methods) {
|
||||
for (const method in build.methods) {
|
||||
js += build.methods[method].toString() + ','
|
||||
}
|
||||
}
|
||||
if (build.usingComponents) {
|
||||
Object.assign(json, build.usingComponents)
|
||||
}
|
||||
if (build.style) {
|
||||
wxss += build.style
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 加入其他自定义标签
|
||||
for (const item of config.customElements) {
|
||||
if (platform === 'uni-app') {
|
||||
if (item.platforms) {
|
||||
wxml += '<!-- #ifdef ' + item.platforms.join(' || ').toUpperCase() + ' -->'
|
||||
}
|
||||
voidTags += item.name + ','
|
||||
wxml += '<' + item.name + ' v-else-if="n.name==\'' + item.name + '\'" :class="n.attrs.class" :style="n.attrs.style"'
|
||||
if (item.attrs) {
|
||||
for (const attr of item.attrs) {
|
||||
wxml += ' :' + attr + '="n.attrs'
|
||||
if (attr.includes('-')) {
|
||||
wxml += '[\'' + attr + '\']"'
|
||||
} else {
|
||||
wxml += '.' + attr + '"'
|
||||
}
|
||||
}
|
||||
}
|
||||
wxml += ' />'
|
||||
if (item.platforms) {
|
||||
wxml += '<!-- #endif -->'
|
||||
}
|
||||
} else if (!item.platforms || item.platforms.join(',').toLowerCase().includes(platform)) {
|
||||
voidTags += item.name + ','
|
||||
wxml += '<' + item.name + ' wx:elif="{{n.name==\'' + item.name + '\'}}" class="{{n.attrs.class}}" style="{{n.attrs.style}}"'
|
||||
if (item.attrs) {
|
||||
for (const attr of item.attrs) {
|
||||
wxml += ' ' + attr + '="{{n.attrs'
|
||||
if (attr.includes('-')) {
|
||||
wxml += '[\'' + attr + '\']}}"'
|
||||
} else {
|
||||
wxml += '.' + attr + '}}"'
|
||||
}
|
||||
}
|
||||
}
|
||||
wxml += ' />'
|
||||
}
|
||||
}
|
||||
|
||||
return through2.obj(function (file, _, callback) {
|
||||
if (file.isBuffer()) {
|
||||
// src 目录
|
||||
if (file.base.includes('src')) {
|
||||
let content = file.contents.toString()
|
||||
if (file.basename === 'index.js' || file.basename === 'mp-html.vue') {
|
||||
// 注册插件列表
|
||||
if (platform === 'uni-app') {
|
||||
content = content.replace(/const\s*plugins\s*=\s*\[\]/, `${pluginImports}const plugins=[${plugins}]`)
|
||||
} else {
|
||||
content = content.replace(/plugins\s*=\s*\[\]/, `plugins=[${plugins}]`)
|
||||
}
|
||||
} else if (file.basename === 'parser.js') {
|
||||
// 设置标签名选择器
|
||||
content = content.replace(/tagSelector\s*=\s*{}/, `tagSelector=${JSON.stringify(tagSelector)}`)
|
||||
// 设置自闭合标签
|
||||
.replace(/voidTags\s*:\s*makeMap\('/, 'voidTags: makeMap(\'' + voidTags)
|
||||
} else if (file.basename === 'node.wxml') {
|
||||
// 引入模板
|
||||
content = content.replace(/<!--\s*insert\s*-->/, wxml)
|
||||
} else if (file.basename === 'node.js') {
|
||||
// 引入方法
|
||||
content = content.replace(/methods\s*:\s*{/, 'methods:{' + js)
|
||||
} else if (file.basename === 'node.wxss') {
|
||||
// 引入样式
|
||||
content = wxss + content
|
||||
} else if (file.basename === 'node.json') {
|
||||
// 引入组件声明
|
||||
const comps = JSON.stringify(json).slice(1, -1)
|
||||
if (comps) {
|
||||
content = content.replace(/"usingComponents"\s*:\s*{/, '"usingComponents":{' + comps + ',')
|
||||
}
|
||||
} else if (file.basename === 'node.vue') {
|
||||
// 引入 vue
|
||||
content = content.replace(/<!--\s*insert\s*-->/, wxml)
|
||||
.replace(/methods\s*:\s*{/, 'methods:{' + js)
|
||||
.replace('<style>', '<style>' + wxss.replace(/\.[a-zA-Z_][^)}]*?[{,]/g, '/deep/ $&')).replace(/,url/g, ', url')
|
||||
let importComp = ''
|
||||
let comps = ''
|
||||
for (let item in json) {
|
||||
const val = json[item]
|
||||
// 插件无法通过这种方式引入
|
||||
if (val.includes('plugin://')) continue
|
||||
item = item.replace(/-([a-z])/g, (_, $1) => $1.toUpperCase())
|
||||
importComp += 'import ' + item + " from '" + val + "'\n"
|
||||
comps += item + ',\n'
|
||||
}
|
||||
content = content.replace('<script>', '<script>\n' + importComp)
|
||||
.replace(/components\s*:\s*{/, 'components: {\n' + comps)
|
||||
} else if (file.basename === 'local.html' && wxss) {
|
||||
// 引入样式
|
||||
content = '<style>' + wxss + '</style>' + content
|
||||
}
|
||||
file.contents = Buffer.from(content)
|
||||
for (const item in builds) {
|
||||
if (builds[item].handler) {
|
||||
builds[item].handler(file, platform)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// plugins 目录
|
||||
const name = file.relative.split(path.sep)[0]
|
||||
const build = builds[name]
|
||||
// 本平台不支持使用
|
||||
if (!build || file.extname === '.md' || file.basename === 'build.js') {
|
||||
callback()
|
||||
return
|
||||
}
|
||||
// import
|
||||
if (build.import) {
|
||||
if (typeof build.import === 'string') {
|
||||
if (file.relative.includes(build.import)) {
|
||||
file.import = true
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < build.import.length; i++) {
|
||||
if (file.relative.includes(build.import[i])) {
|
||||
file.import = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (build.handler) {
|
||||
build.handler(file, platform)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.push(file)
|
||||
callback()
|
||||
})
|
||||
},
|
||||
/**
|
||||
* @description 引入样式文件到 node.wxss 中
|
||||
*/
|
||||
importCss () {
|
||||
let css = ''
|
||||
return through2.obj(function (file, _, callback) {
|
||||
if (file.isBuffer()) {
|
||||
let content = file.contents.toString()
|
||||
// 要被引入的文件
|
||||
if (file.import) {
|
||||
css += content
|
||||
callback()
|
||||
return
|
||||
}
|
||||
// 引入到对应位置
|
||||
if (file.basename === 'node.wxss') {
|
||||
content = css + content
|
||||
} else if (file.basename === 'node.vue') {
|
||||
content = content.replace('<style>', '<style>' + css.replace(/\.[a-z_][^)}]+?[{,]/g, '/deep/ $&')).replace(/,url/g, ', url')
|
||||
} else if (file.basename === 'local.html' && css) {
|
||||
content = '<style>' + css + '</style>' + content
|
||||
}
|
||||
file.contents = Buffer.from(content)
|
||||
}
|
||||
this.push(file)
|
||||
callback()
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user