diyi-ui

diyi A Vue.js UI

Usage no npm install needed!

<script type="module">
  import diyiUi from 'https://cdn.skypack.dev/diyi-ui';
</script>

README

npm

Image text

A Vue.js UI

Build Setup

# install dependencies
npm install diyi-ui -S

import Vue from 'vue'
import diyiUI from 'diyi-ui'
Vue.use(diyiUI)

#采用的是样式分离,需要单独引入样式
import 'diyi-ui/dist/diyi-ui.min.css'

  • 解决vuepress build失败的问题

在node_modules找到@vuepress/core/lib/node/build/index.js, 把下面这段内容替换掉即可,然后执行npm run build:doc可顺利打包



'use strict'

const EventEmitter = require('events').EventEmitter
const webpack = require('webpack')
const readline = require('readline')
const escape = require('escape-html')
const HtmlWebpackPlugin = require('vuepress-html-webpack-plugin')
const merge = require('webpack-merge')
const { chalk, fs, path, logger, env, performance } = require('@vuepress/shared-utils')
const createClientConfig = require('../webpack/createClientConfig')
const createServerConfig = require('../webpack/createServerConfig')
// const { createBundleRenderer } = require('vue-server-renderer')
const { normalizeHeadTag, applyUserWebpackConfig } = require('../util/index')
const { version } = require('../../../package')

/**
 * Expose Build Process Class.
 */

module.exports = class Build extends EventEmitter {
  constructor (context) {
    super()
    this.context = context
    this.outDir = this.context.outDir
  }

  /**
   * Doing somthing before render pages, e.g. validate and empty output directory,
   * prepare webpack config.
   *
   * @returns {Promise<void>}
   * @api public
   */

  async process () {
    if (this.context.cwd === this.outDir) {
      throw new Error('Unexpected option: "outDir" cannot be set to the current working directory')
    }

    this.context.resolveCacheLoaderOptions()
    await fs.emptyDir(this.outDir)
    logger.debug('Dist directory: ' + chalk.gray(this.outDir))
    this.prepareWebpackConfig()
  }

  /**
   * Compile and render pages.
   *
   * @returns {Promise<void>}
   * @api public
   */

  async render () {
    // compile!
    // const context = {
    //   url: page.path,
    //   userHeadTags: this.userHeadTags,
    //   title: 'VuePress',
    //   lang: 'en',
    //   description: '',
    //   version
    // }

    const stats = await compile([merge(this.clientConfig, {
      plugins: [
        new HtmlWebpackPlugin({
          template: this.context.devTemplate
        })
      ]
    })])
    // const serverBundle = require(path.resolve(this.outDir, 'manifest/server.json'))
    // const clientManifest = require(path.resolve(this.outDir, 'manifest/client.json'))

    // remove manifests after loading them.
    // await fs.remove(path.resolve(this.outDir, 'manifest'))

    // ref: https://github.com/vuejs/vuepress/issues/1367
    if (!this.clientConfig.devtool && (!this.clientConfig.plugins
      || !this.clientConfig.plugins.some(p =>
        p instanceof webpack.SourceMapDevToolPlugin
        || p instanceof webpack.EvalSourceMapDevToolPlugin
      ))) {
      await workaroundEmptyStyleChunk(stats, this.outDir)
    }

    // // create server renderer using built manifests
    // this.renderer = createBundleRenderer(serverBundle, {
    //   clientManifest,
    //   runInNewContext: false,
    //   inject: false,
    //   shouldPrefetch: this.context.siteConfig.shouldPrefetch || (() => true),
    //   template: await fs.readFile(this.context.ssrTemplate, 'utf-8')
    // })

    // pre-render head tags from user config
    // filter out meta tags for they will be injected in updateMeta.js
    this.userHeadTags = (this.context.siteConfig.head || [])
      .filter(([headTagType]) => headTagType !== 'meta')
      .map(renderHeadTag)
      .join('\n    ')

    // if the user does not have a custom 404.md, generate the theme's default
    if (!this.context.pages.some(p => p.path === '/404.html')) {
      await this.context.addPage({ path: '/404.html' })
    }

    // render pages
    logger.wait('Rendering static HTML...')

    // const pagePaths = await Promise.all(
    //   this.context.pages.map(page => this.renderPage(page))
    // )

    readline.clearLine(process.stdout, 0)
    readline.cursorTo(process.stdout, 0)

    // await this.context.pluginAPI.applyAsyncOption('generated', pagePaths)

    // DONE.
    const relativeDir = path.relative(this.context.cwd, this.outDir)
    logger.success(`Generated static files in ${chalk.cyan(relativeDir)}.`)
    const { duration } = performance.stop()
    logger.developer(`It took a total of ${chalk.cyan(`${duration}ms`)} to run the ${chalk.cyan('vuepress build')}.`)
    console.log()
  }

  /**
   * Prepare webpack config under build.
   *
   * @api private
   */

  prepareWebpackConfig () {
    this.clientConfig = createClientConfig(this.context).toConfig()
    this.serverConfig = createServerConfig(this.context).toConfig()

    const userConfig = this.context.siteConfig.configureWebpack
    if (userConfig) {
      this.clientConfig = applyUserWebpackConfig(userConfig, this.clientConfig, false)
      this.serverConfig = applyUserWebpackConfig(userConfig, this.serverConfig, true)
    }
  }

  /**
   * Render page
   *
   * @param {Page} page
   * @returns {Promise<string>}
   * @api private
   */

  async renderPage (page) {
    const pagePath = decodeURIComponent(page.path)

    const context = {
      url: page.path,
      userHeadTags: this.userHeadTags,
      title: 'VuePress',
      lang: 'en',
      description: '',
      version
    }

    let html
    try {
      html = await this.renderer.renderToString(context)
    } catch (e) {
      console.error(logger.error(chalk.red(`Error rendering ${pagePath}:`), false))
      throw e
    }
    const filename = pagePath.replace(/\/$/, '/index.html').replace(/^\//, '')
    const filePath = path.resolve(this.outDir, filename)
    await fs.ensureDir(path.dirname(filePath))
    await fs.writeFile(filePath, html)
    return filePath
  }
}

/**
 * Compile a webpack application and return stats json.
 *
 * @param {Object} config
 * @returns {Promise<Object>}
 */

function compile (config) {
  return new Promise((resolve, reject) => {
    webpack(config, (err, stats) => {
      if (err) {
        return reject(err)
      }
      if (stats.hasErrors()) {
        stats.toJson().errors.forEach(err => {
          console.error(err)
        })
        reject(new Error(`Failed to compile with errors.`))
        return
      }
      if (env.isDebug && stats.hasWarnings()) {
        stats.toJson().warnings.forEach(warning => {
          console.warn(warning)
        })
      }
      resolve(stats.toJson({ modules: false }))
    })
  })
}

/**
 * Render head tag
 *
 * @param {Object} tag
 * @returns {string}
 */

function renderHeadTag (tag) {
  const { tagName, attributes, innerHTML, closeTag } = normalizeHeadTag(tag)
  return `<${tagName}${renderAttrs(attributes)}>${innerHTML}${closeTag ? `</${tagName}>` : ``}`
}

/**
 * Render html attributes
 *
 * @param {Object} attrs
 * @returns {string}
 */

function renderAttrs (attrs = {}) {
  const keys = Object.keys(attrs)
  if (keys.length) {
    return ' ' + keys.map(name => `${name}="${escape(attrs[name])}"`).join(' ')
  } else {
    return ''
  }
}

/**
 * find and remove empty style chunk caused by
 * https://github.com/webpack-contrib/mini-css-extract-plugin/issues/85
 * TODO remove when it's fixed
 *
 * @param {Object} stats
 * @param {String} outDir
 * @returns {Promise<void>}
 */

async function workaroundEmptyStyleChunk (stats, outDir) {
  const styleChunk = stats.children[0].assets.find(a => {
    return /styles\.\w{8}\.js$/.test(a.name)
  })
  if (!styleChunk) return
  const styleChunkPath = path.resolve(outDir, styleChunk.name)
  const styleChunkContent = await fs.readFile(styleChunkPath, 'utf-8')
  await fs.remove(styleChunkPath)
  // prepend it to app.js.
  // this is necessary for the webpack runtime to work properly.
  const appChunk = stats.children[0].assets.find(a => {
    return /app\.\w{8}\.js$/.test(a.name)
  })
  const appChunkPath = path.resolve(outDir, appChunk.name)
  const appChunkContent = await fs.readFile(appChunkPath, 'utf-8')
  await fs.writeFile(appChunkPath, styleChunkContent + appChunkContent)
}