npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

manual-filetr

v1.1.5

Published

座舱电子手册资源筛选命令

Downloads

9

Readme

鉴于电子手册开发过程中,打包资源过大&需要手动清除,存在资源问题,现在做命令行工具

具体使用方法: 1、在本地先配置gulp工具 代码如下:

// 引入必要的模块
const gulp = require('gulp');
const jsonminify = require('gulp-jsonminify');
const through2 = require('through2');
const filter = require('gulp-filter');
var uglify = require('gulp-uglify');
//导出源资源
gulp.task('source1',()=>{
    return gulp.src('./dist/build/h5/assets/**/*', {encoding:false}).pipe(gulp.dest('build/h5/assets'))
    })

gulp.task('source2',()=>{
    return gulp.src('./dist/build/h5/*.js', {encoding:false} ).pipe(gulp.dest('build/h5'))
    })
gulp.task('source3',()=>{
    return gulp.src('./dist/build/h5/*.html', {encoding:false}).pipe(gulp.dest('build/h5'))
    })
gulp.task('source4',()=>{
    return gulp.src('./dist/build/h5/static/js/*', {encoding:false}).pipe(gulp.dest('build/h5/static/js'))
    })
gulp.task('source5',()=>{
    return gulp.src('./dist/build/h5/static/packages/*', {encoding:false}).pipe(gulp.dest('build/h5/static/packages'))
    })
gulp.task('source6',()=>{
    return gulp.src('./dist/build/h5/static/*.css', {encoding:false}).pipe(gulp.dest('build/h5/static')) 
    })
gulp.task('source7',()=>{
    return gulp.src('./dist/build/h5/static/*.gz', {encoding:false}).pipe(gulp.dest('build/h5/static'))
    })
gulp.task('source8',()=>{
        return gulp.src('./dist/build/h5/static/manuals/T1E24FL-8155/*.json', {encoding:false})
        .pipe(jsonminify())
        .pipe(gulp.dest('build/h5/static/manuals/T1E24FL-8155'))
    })
gulp.task('source9',()=>{
    return gulp.src('./dist/build/h5/static/manuals/T1E24FL-8155/*.js')
    .pipe(uglify())
    .pipe(gulp.dest('build/h5/static/manuals/T1E24FL-8155'))
})
//导出user-manual用户手册资源
gulp.task('user-manual1',()=>{
    const mdFilter = filter('**/*.md', {restore: true});
	const jsonFilter = filter('**/*.json', {restore:true });
    return gulp.src('./dist/build/h5/static/manuals/T1E24FL-8155/user-manual/**/*', {encoding:false})
    .pipe(mdFilter)
    .pipe(through2.obj(function (file, enc, callback) {
        if (file.isBuffer()) {
            let content = file.contents.toString();
            content = content.replace(/\s+/g, ' ').trim(); // 去除多余的空白字符
            file.contents = Buffer.from(content);
        }
        callback(null, file);
    }))
    .pipe(mdFilter.restore)
    .pipe(jsonFilter)
    .pipe(jsonminify())
    .pipe(jsonFilter.restore)
    .pipe(gulp.dest('build/h5/static/manuals/T1E24FL-8155/user-manual/'))
})
gulp.task('user-manual2',()=>{
    const mdFilter = filter('**/*.md', {restore: true});
	const jsonFilter = filter('**/*.json', {restore:true });
    return gulp.src('./dist/build/h5/static/bdvr/**/*', {encoding:false})
    .pipe(mdFilter)
    .pipe(through2.obj(function (file, enc, callback) {
        if (file.isBuffer()) {
            let content = file.contents.toString();
            content = content.replace(/\s+/g, ' ').trim(); // 去除多余的空白字符
            file.contents = Buffer.from(content);
        }
        callback(null, file);
    }))
    .pipe(mdFilter.restore)
    .pipe(jsonFilter)
    .pipe(jsonminify())
    .pipe(jsonFilter.restore)
    .pipe(gulp.dest('build/h5/static/bdvr/'))
})
//导出center-console中控手册资源
gulp.task('center-console',()=>{
    const mdFilter = filter('**/*.md', {restore: true});
	const jsonFilter = filter('**/*.json', {restore:true });
    return gulp.src('./dist/build/h5/static/manuals/T1E24FL-8155/center-console/**/*', {encoding:false})
    .pipe(mdFilter)
    .pipe(through2.obj(function (file, enc, callback) {
        if (file.isBuffer()) {
            let content = file.contents.toString();
            content = content.replace(/\s+/g, ' ').trim(); // 去除多余的空白字符
            file.contents = Buffer.from(content);
        }
        callback(null, file);
    }))
    .pipe(mdFilter.restore)
    .pipe(jsonFilter)
    .pipe(jsonminify())
    .pipe(jsonFilter.restore)
    .pipe(gulp.dest('build/h5/static/manuals/T1E24FL-8155/center-console/'))
})

//导出quick-start快速入门资源
gulp.task('quick-start',()=>{
    const mdFilter = filter('**/*.md', {restore: true});
	const jsonFilter = filter('**/*.json', {restore:true });
    return gulp.src('./dist/build/h5/static/manuals/T1E24FL-8155/quick-start/**/*', {encoding:false})
    .pipe(mdFilter)
    .pipe(through2.obj(function (file, enc, callback) {
        if (file.isBuffer()) {
            let content = file.contents.toString();
            content = content.replace(/\s+/g, ' ').trim(); // 去除多余的空白字符
            file.contents = Buffer.from(content);
        }
        callback(null, file);
    }))
    .pipe(mdFilter.restore)
    .pipe(jsonFilter)
    .pipe(jsonminify())
    .pipe(jsonFilter.restore)
    .pipe(gulp.dest('build/h5/static/manuals/T1E24FL-8155/quick-start/'))
})
//导出new-features新功能资源
gulp.task('new-features',()=>{
    const mdFilter = filter('**/*.md', {restore: true});
	const jsonFilter = filter('**/*.json', {restore:true });
    return gulp.src('./dist/build/h5/static/manuals/T1E24FL-8155/new-features/**/*', {encoding:false})
    .pipe(mdFilter)
    .pipe(through2.obj(function (file, enc, callback) {
        if (file.isBuffer()) {
            let content = file.contents.toString();
            content = content.replace(/\s+/g, ' ').trim(); // 去除多余的空白字符
            file.contents = Buffer.from(content);
        }
        callback(null, file);
    }))
    .pipe(mdFilter.restore)
    .pipe(jsonFilter)
    .pipe(jsonminify())
    .pipe(jsonFilter.restore)
    .pipe(gulp.dest('build/h5/static/manuals/T1E24FL-8155/new-features/'))
})
// Markdown压缩任务
gulp.task('minify', () => {
    const mdFilter = filter('**/*.md', {restore: true});
	const jsonFilter = filter('**/*.json', {restore:true });
    return gulp.src('./dist/build/h5/**/*', {encoding:false}) // 指定源文件路径
        .pipe(mdFilter)
        .pipe(through2.obj(function (file, enc, callback) {
            if (file.isBuffer()) {
                let content = file.contents.toString();
                content = content.replace(/\s+/g, ' ').trim(); // 去除多余的空白字符
                file.contents = Buffer.from(content);
            }
            callback(null, file);
        }))
        .pipe(mdFilter.restore)
        .pipe(jsonFilter)
        .pipe(jsonminify())
        .pipe(jsonFilter.restore)
        .pipe(gulp.dest('build/h5'))
});

gulp.task('source', gulp.series(['source1','source2','source3','source4','source5','source6','source7','source8','source9']));
gulp.task('user-manual', gulp.parallel(['user-manual1','user-manual2']));
// 默认任务,执行所有压缩任务
gulp.task('default', gulp.parallel(['minify']));

2、npm i manual-filetr rimraf 配置package.josn的脚本命令

 "scripts": {
    "filter": "manual",
	 "rimraf": "rimraf ./build/h5",
	"filter:upgrade": "rimraf ./dist/build/h5 && cross-env NODE_ENV=production BUILD_TARGET=T1E24FL-8155 INCREASE_BUILD_NUM=true UNI_PLATFORM=h5 vue-cli-service uni-build",
    "filter:current": "rimraf ./dist/build/h5 && cross-env NODE_ENV=production BUILD_TARGET=T1E24FL-8155 UNI_PLATFORM=h5 vue-cli-service uni-build",
 }

3、配置压缩资源文件postgulpbuild.js

const fs = require('fs')
const path = require('path')
const pump = require('pump')
const crypto = require('crypto')
const compressing = require('compressing')
const manifest = require("./src/manifest.json")

// 更新html文件theme默认主题属性值
function updateFileTheme(from, to, theme) {
  let content = fs.readFileSync(from, 'utf-8')
  content = content.replace(/theme="[^\\"]*"/, `theme="${theme}" theme-background-none`)
  fs.writeFileSync(to, content)
}

async function zipDirectory(dir, to) {
  const stream = new compressing.zip.Stream()
  fs.readdirSync(dir).forEach(name => stream.addEntry(path.join(dir, name)))
  const destStream = fs.createWriteStream(to)
  return await new Promise((resolve, reject) => pump(stream, destStream, (err) => err && reject(err) || resolve()))
}

function hashFile(file) {
  const hash = crypto.createHash('md5')
  hash.update(fs.readFileSync(file))
  return hash.digest('hex')
}

async function removeFile(file) {
  try {
    await fs.promises.unlink(file)
    return true
  } catch {
    return false
  }
}

async function removeDir(dir) {
  try {
    await fs.promises.rmdir(dir, { recursive: true })
    return true
  } catch {
    return false
  }
}

async function postBuild() {
  // const buildLocalManual = false //是否编译本地中控电子手册
  const targetVehicleModel = process.env.BUILD_TARGET || manifest.versionTarget
  const vehiclePath = targetVehicleModel ? targetVehicleModel + '/' : ''
  const h5RootPath = path.join(__dirname, './build/h5/')
  const packagesRootPath = path.join(__dirname, `./build/packages/${vehiclePath}`)
  // 创建目录(如果不存在)
  try {
    await fs.promises.stat(packagesRootPath)
  } catch (e) {
    await fs.promises.mkdir(packagesRootPath, { recursive: true })
  }

  // 生成主题一引导文件:html-0.html
  updateFileTheme('./build/h5/index.html', './build/h5/index-0.html', "light")
  updateFileTheme('./build/h5/index.html', './build/h5/index-1.html', "dark")
  // 生成主题一引导文件:html-1.html
  // updateFileTheme('./dist/build/h5/index.html', './dist/build/h5/index-1.html', "tech")
  // 生成主题一引导文件:html-2.html
  // updateFileTheme('./dist/build/h5/index.html', './dist/build/h5/index-2.html', "classic")

  // 删除不必要的目录
  await removeDir(path.join(h5RootPath, '/static/packages'))

  // 删除不必要的电子手册文件夹
  const manualDirs = await fs.promises.readdir(path.join(h5RootPath, '/static/manuals'))
  for (let i = 0; i < manualDirs.length; i++) {
    const vehicleModel = manualDirs[i]
    if (vehicleModel === targetVehicleModel) {
      // if (buildLocalManual) {
        // 发布本地电子手册用(删除智能电子手册内容)
        // await removeDir(path.join(h5RootPath, `/static/manuals/${vehicleModel}/center-console`))
        // await removeDir(path.join(h5RootPath, `/static/manuals/${vehicleModel}/new-features`))
        // await removeDir(path.join(h5RootPath, `/static/manuals/${vehicleModel}/quick-start`))
        // await removeDir(path.join(h5RootPath, `/static/manuals/${vehicleModel}/user-manual`))
      // } else {
        // 发布智能电子手册用(删除本地电子手册内容)
        await removeDir(path.join(h5RootPath, `/static/manuals/${vehicleModel}/local`))
      // }
      // 其他文件删除
      await removeFile(path.join(h5RootPath, `/static/manuals/${vehicleModel}/parse-html.js`))
      continue
    }
    // 非发布的车型(删除其他车型电子手册内容)
    await removeDir(path.join(h5RootPath, `/static/manuals/${vehicleModel}`))
  }

  // 打包,计算MD5,更新app-latest.json信息
  const version = manifest.versionName
  const build = manifest.versionCode
  const packageFile = `car-manual-h5_${targetVehicleModel || 'unkown'}_${version.replace(/\./g, '_')}_${build}.zip`
  const packageFilePath = path.join(packagesRootPath, packageFile)
  await zipDirectory(h5RootPath, packageFilePath)
  const pkgHash = hashFile(packageFilePath)
  const pkgUrl = `${manifest.h5.publicRemotePath}/packages/${vehiclePath}${packageFile}`
  fs.writeFileSync(path.join(packagesRootPath, 'app-latest.json'), JSON.stringify({ version, build, pkgUrl, pkgHash }))
  console.log("Package Generated111111111111", packageFilePath)
  console.log("Update app-latest.json1111111111", { version, build, pkgUrl, pkgHash })
}


console.info("Post-build starting...")
postBuild().finally(() => {
  console.info("Post-build complete.")
})