util.js 3.74 KB
const path = require('path')
const fs = require('fs')

const pagesNameMap = Object.create(null)

function cacheFileInfo (resourcePath, ...arg) {
  pagesNameMap[resourcePath] = Object.assign({}, pagesNameMap[resourcePath], ...arg)
}

function getFileInfo (resourcePath) {
  return pagesNameMap[resourcePath] || {}
}

// 单文件的名字+hash
// TODO: 调试时取个全名
var hash = require('hash-sum')
const cache = Object.create(null)
function getCompNameBySrc (file) {
  return cache[file] || (cache[file] = `${getNameByFile(file)}$${hash(file)}`)
}

// 根据路径获得组件名
function getNameByFile (dir) {
  // const arr = dir.match(/[pages?/components?]\/(.*?)(\/)/)
  const arr = dir.match(/pages\/(.*?)\//)
  if (arr && arr[1]) {
    return arr[1]
  }
  return path.parse(dir).name
}

function getKeyFromObjByVal (obj, val) {
  for (const i in obj) {
    if (obj[i] === val) {
      return i
    }
  }
}

function getPageSrc (pageName) {
  return path.parse(pageName).dir ? pageName : `pages/${pageName}/${pageName}`
}

// TODO, 这儿应该按照 main.js 导出的 config 来进行 isApp isPage 识别,暂时不改,下次大版本升级 loader 的时候改
// 计算目标输出的路径等信息
// pageType 默认为 null === component, 目前共 3 种类型: component, app, page
function resolveTarget (dir, entry) {
  const originName = getKeyFromObjByVal(entry, dir)
  const name = originName || getNameByFile(dir)
  const isApp = name === 'app'
  const pageType = isApp ? 'app' : (originName ? 'page' : 'component')
  const isPage = pageType === 'page'

  let src = 'app'
  if (isPage) {
    src = getPageSrc(name)
  }

  return { pageType, src, name, isApp, isPage }
}

// 简单的转换驼峰大写为中横线
const hyphenateRE = /([^-])([A-Z])/g
function covertCCVar (str) {
  return str
    .replace(hyphenateRE, '$1-$2')
    .replace(hyphenateRE, '$1-$2')
    .toLowerCase()
}

// 缓存所有的 slots 节点,生成一个文件
const slotsCache = Object.create(null)
const importCodeCache = Object.create(null)

function cacheSlots (slots, importCode) {
  Object.keys(slots).forEach(k => {
    slotsCache[k] = slots[k]
  })
  importCodeCache[importCode] = importCode
}
function getSlots () {
  const allImportCode = Object.keys(importCodeCache).map(v => importCodeCache[v]).join('\n').replace('<import src="slots" />', '')
  const allSlots = Object.keys(slotsCache).map(v => slotsCache[v].code).join('\n')
  return allImportCode + allSlots
}

// 包大小优化: build 模式不需要美化 wxml
const jsBeautify = require('js-beautify')
const isProduction = process.env.NODE_ENV === 'production'
function htmlBeautify (content) {
  const htmlBeautifyOptions = {
    // wrap_line_length: '80',
    indent_size: 2,
    preserve_newlines: false,
    max_preserve_newlines: 0,
    e4x: true,
    unformatted: ['a', 'span', 'img', 'code', 'pre', 'sub', 'sup', 'em', 'strong', 'b', 'i', 'u', 'strike', 'big', 'small', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']
  }

  if (isProduction) {
    return content
  }
  return jsBeautify.html(content, htmlBeautifyOptions)
}

function getBabelrc (src) {
  if (src && fs.existsSync(src)) {
    return src
  }
  const curBabelRc = path.resolve('./.babelrc')
  if (fs.existsSync(curBabelRc)) {
    return curBabelRc
  }
  return ''
}

function getPathPrefix (src) {
  const length = src.split('/').length - 1
  return `${'../'.repeat(length)}`
}

const defaultStylePart = {
  type: 'style',
  content: '\n',
  start: 0,
  attrs: {},
  end: 1,
  map: {
    version: 3,
    sources: [],
    names: [],
    mappings: '',
    sourcesContent: []
  }
}

module.exports = {
  defaultStylePart,
  cacheFileInfo,
  getFileInfo,
  getCompNameBySrc,
  resolveTarget,
  covertCCVar,
  cacheSlots,
  getSlots,
  htmlBeautify,
  getBabelrc,
  getPathPrefix,
  getPageSrc
}