Browse Source

文件缓存修改

lilinsen 6 years ago
parent
commit
475aeb7177
4 changed files with 335 additions and 339 deletions
  1. 3 0
      .gitignore
  2. 0 1
      build/webpack.doc.base.conf.js
  3. 132 0
      scripts/contrast.js
  4. 200 338
      scripts/mdToVue.js

+ 3 - 0
.gitignore

@@ -14,3 +14,6 @@ docshashCache.text
 srchashCache.text
 srchashCache.text
 localsrc.cache
 localsrc.cache
 localdocs.cache
 localdocs.cache
+cache/src.cache
+cache/mdToVue.cache
+cache/docs.cache

+ 0 - 1
build/webpack.doc.base.conf.js

@@ -3,7 +3,6 @@ const webpackBaseConf = require('./webpack.base.conf.js');
 const HtmlWebpackPlugin = require('html-webpack-plugin');
 const HtmlWebpackPlugin = require('html-webpack-plugin');
 const MiniCssExtractPlugin = require("mini-css-extract-plugin");
 const MiniCssExtractPlugin = require("mini-css-extract-plugin");
 const merge = require('webpack-merge');
 const merge = require('webpack-merge');
-
 const mdtohtml = require('../scripts/mdToVue');
 const mdtohtml = require('../scripts/mdToVue');
 const isDev = process.env.NODE_ENV === 'development';
 const isDev = process.env.NODE_ENV === 'development';
 
 

+ 132 - 0
scripts/contrast.js

@@ -0,0 +1,132 @@
+const path = require('path');
+const fs = require('fs');
+let { hashElement } = require('folder-hash');
+/**
+ * 文件对比
+ * entry {string} 要对比的文件路径
+ * include {array} 要对比的文件格式 以数组形式
+ */
+class contrast{
+    constructor(options){        
+        this.entry = options.entry; 
+        this.include =  options.include || ['*.md'] ;       
+        this.fileHash = null;
+        this.oldHash = null;
+        this.differentHash = null;        
+        this.outPath = path.join("./cache",options.entry.split(path.sep).pop().replace(/(\.md|\.js)/,'')+ '.cache');       
+        
+    }
+    run(){
+        let _that = this;
+        return new Promise((reslove,reject)=>{
+            _that.start().then(res=>{          
+                this.getCache().then(out=>{
+                    _that.compare();
+                    _that.record(); 
+                    reslove(_that.differentHash);
+                },err=>{
+                    reslove(_that.fileHash);
+                    _that.record();   
+                })            
+            })
+        })        
+    }
+    start(){
+        let _that = this;
+        return new Promise((reslove,reject)=>{
+            hashElement(_that.entry, {
+                folders: { exclude: ['.*', 'node_modules', 'test_coverage','__test__','img','svg'] },
+                files: { include: _that.include, },
+                matchBasename: true
+            }).then(res=>{   
+                //获取当前hash
+                _that.fileHash = _that.arraydownGrade(res);  
+                if(_that.fileHash){
+                    reslove(_that.fileHash)  
+                }else{
+                    reject("err")
+                }       
+            })
+        })
+        
+    }
+    arraydownGrade(ay){
+        let arys = {};
+        let paths = "";
+        function downGrade(data){                
+            if(data.children && data.children.constructor == Array ){
+                paths = data.name;
+                data.children.map(item => {
+                    downGrade(item)                                                
+                })
+            }else{     
+                let key = data.name.replace(/(\.md|\.js)/,'');
+                if(key =="doc"){
+                    arys[paths] = data.hash;
+                }else{
+                    arys[key] = data.hash;
+                }                    
+            }
+        }
+        downGrade(ay)
+        return arys;
+    }
+    /**
+     * 获取本地hash记录
+     */
+    getCache(){
+        let _that = this;
+        return new Promise((reslove,reject)=>{
+            fs.readFile(this.outPath,"utf8",(err,data) => {               
+                if(!err){
+                    _that.oldHash = JSON.parse(data);
+                    reslove();
+                }else{  
+                    console.error("There are no cached files in your locality");
+                    reject();
+                }
+            })  
+        })        
+    }
+    compare(){
+        let fileHash = this.fileHash;
+        let oldHash = this.oldHash;
+        let differenthash = {};
+        for(let newkey in fileHash){
+            if(oldHash[newkey]){
+                if(oldHash[newkey] != fileHash[newkey]){
+                    differenthash[newkey] = fileHash[newkey]
+                }
+            }else{
+                differenthash[newkey] = fileHash[newkey]
+            }
+        }
+        this.differentHash = differenthash;      
+    }
+    record(){
+        let _that = this;
+        this.ishasOutFile("./cache").then(res=>{
+            fs.writeFile(_that.outPath,JSON.stringify(_that.fileHash),'utf8',(err,res)=>{ })
+        })        
+        
+    }
+    ishasOutFile(outPath){
+        return new Promise((resolve,reject)=>{
+            fs.stat(outPath,(err,res)=>{       
+                if(err){
+                    fs.mkdir(outPath,err=>{
+                        if(err){
+                            reject(err)
+                        }else{ 
+                            resolve(true)
+                        }               
+                    })
+                }else{                    
+                    resolve(true)
+                }
+            })  
+        })      
+    }
+    
+}
+module.exports = contrast

+ 200 - 338
scripts/mdToVue.js

@@ -1,360 +1,222 @@
-const fs = require('fs');
 const path = require('path');
 const path = require('path');
-//hash获取工具
+const fs = require('fs');
+const nodeFilelist  = require('node-filelist');
 let { hashElement } = require('folder-hash');
 let { hashElement } = require('folder-hash');
-//marked转换工具
+let { version } = require("../package.json");
 let marked = require('marked');
 let marked = require('marked');
+let contrast = require('./contrast');
+let rimraf = require("rimraf");
 if (!marked) {
 if (!marked) {
     console.log('you need npm i marked -D!');
     console.log('you need npm i marked -D!');
 }
 }
-var nodeFilelist  = require('node-filelist');
-//文件监听
-let Chokidar = require('chokidar');
-// 基本配置文件信息
-let {version} = require("../package.json");
-//vue js脚本
-//获取所有文件列表
-let fileList  = [];
-let Articlehead = '';
-let Articleheadcount = 0;
-// maked文件配置
-var rendererMd = new marked.Renderer();
-//maked文件规则
-rendererMd.code = function (code, infostring, escaped) {
-    var lang = (infostring || '').match(/\S*/)[0];
-    if (this.options.highlight) {
-        var out = this.options.highlight(code, lang);
-        if (out != null && out !== code) {
-            escaped = true;
-            code = out;
-        }
-    }
-    if (!lang) {
-        return '<pre><code>'
-            + (escaped ? code : escape(code, true))
-            + '</code></pre>';
-    }
-
-    if (lang === 'html') {
-        code = code.replace(/@latest/g, '@' + version)
-    }
-
-    return '<hide><pre class="prettyprint"><span class="lang">' + lang + '</span><div class="code-wrapper"><code class="'
-        + this.options.langPrefix
-        + escape(lang, true)
-        + '">'
-        + (escaped ? code : escape(code, true))
-        + '</code></div><i class="copy" copy="copy" data-clipboard-action="copy" data-clipboard-target="code" title="复制代码"></i><i toast="toast" title="全屏"></i></pre></hide>\n';
-};
-rendererMd.heading = function (text,level){
-   
-    // 如果需要 marklist;
-   
-    if(level==2){
-        Articleheadcount++; 
-        Articlehead +=`<li @click="leavelchose(`+Articleheadcount+`)" :class="levalcur==`+Articleheadcount+`?'cur':''"  class="level`+Articleheadcount+'"><a href="#head'+Articleheadcount+'">'+text.substr(0,10)+'</a></li>';
-    }
-
-    return "<h"+level+" class='visibility' id='head"+Articleheadcount+"'>"+ text +"</h"+level+">"; 
-};
-marked.setOptions({
-    renderer: rendererMd,
-    highlight: function (code) {
-        return require('highlight.js').highlightAuto(code).value;
-    },
-    tables: true
-}, res => {
-
-})
-/**
- *  是否需要单独处理头部信息
- * @param {text} sorce 替换 头部信息 
- */
-function insert(sorce) {
-    var insert = sorce.indexOf('</h1>');
-
-    if (insert > -1) {
-        return sorce.substring(0, insert) + '<i class="qrcode"><a :href="demourl"><span>请使用手机扫码体验</span><img :src="codeurl" alt=""></a></i>' + sorce.substring(insert, sorce.length);
-    } else {
-        return sorce
-    }
-
-}
-///创建一个空文件
-/**
- * 修复中 
- * @param {string} output  输出路径
- * @param {string} sorce  文件源
- * @param {boole} ishasCode  是否需要二维码 
- */
-function createdFile(output, sorce, param) {
-    var pathSrc = output;    
-    if (param.needCode) {
-        var res = insert(sorce);
-    } else {
-        var res = sorce;
-    }
-    var bufs = `<template><div  @click="dsCode">
-        <div v-if="content" class="layer">
-          <pre><span class="close-box" @click="closelayer"></span><div v-html="content"></div></pre>
-        </div>`+ res + (param.hasMarkList?'<ul class="markList">' +Articlehead + '</ul>':'')+
-        `<nut-backtop :right="50" :bottom="50"></nut-backtop></div></template><script>import root from '../root.js';
-        export default {
-            mixins:[root]
-        }</script>`;       
-        Articlehead = '';
-        Articleheadcount = 0;      
-       
-    fs.writeFile(pathSrc,bufs,'utf8',(err)=>{ })
-}
-/**
- * 目录读取,找到跟文件
- * @fileSrc {string} 打开文件路径
- * @callback {fn} 结束后回调函数
- */
-function readDirRecur(fileSrc, callback) {
-    fs.readdir(fileSrc, function(err, files) {
-      var count = 0
-      var checkEnd = function() {
-        ++count == files.length && callback()
-      }  
-      files.forEach(function(file) {
-        var fullPath = fileSrc + '/' + file;  
-        fs.stat(fullPath, function(err, stats) {
-          if (stats.isDirectory()) {
-              return readDirRecur(fullPath, checkEnd);
-          } else {
-            /*not use ignore files*/
-            if(file[0] == '.') {
-  
-            } else {
-              fileList.push(fullPath)            
-            }
-            checkEnd()
-          }
+class mdVue{   
+    constructor(options){
+        let defaultSetting = {           
+            needCode:true,
+            isbuild:true,
+            hasMarkList:true
+        };
+        this.options =Object.assign(defaultSetting,options);       
+        this.rendererMd = new marked.Renderer();
+        this.marked = marked;
+        let _that = this;    
+        this.Articlehead = "";
+        this.Articleheadcount = 0;
+        this.needHandleFiles = null;
+        this.cachePath = path.join("./cache",options.entry.split(path.sep).pop()+ '.cache');    
+        this.codeHandle();               
+        this.checkSelf().then(res=>{
+            // 检查要编译的文件
+            let ct = new contrast({
+                entry:this.options.entry         
+            }).run().then(res=>{            
+                _that.needHandleFiles = res;
+                _that.ishasOutFile(_that.options.output).then(res=>{
+                    _that.star();
+                });  
+            })  
         })
         })
-      })  
-      //为空时直接回调
-      files.length === 0 && callback()
-    })
-}
-function fileReadStar(filedir,callback){
-    fs.readFile(filedir, 'utf-8', (err, data) => {
-        let html = marked(data); 
-        let mdName = "";
-        let opensName = filedir.replace(/(^.*\/|.md)/g,"");                    
-        //如果是doc文件以前缀 为
-        if (opensName === 'doc') {
-            mdName = filedir.replace(/(^.*packages\/|\/doc\.md)/g,'');
-        } else {
-            //如果不是doc命名的文件
-            mdName = opensName;
-        } 
-        callback({
-            mdName:mdName,
-            html:html
-        })   
-    });
-}
-/**
- * 判断是否位md文件 并进行操作
- * 判断文件是否有改动
- * @src {string} 打开的文件目录
- * @hasobj {obj} hash对象
- * @callback {fn} 回调函数
- */
-function ismd(src,hasobj,callback){
-    //判断文件类型是否是md文件    
-    let filedir = src;  
-    //return new Promise((resolve,reject)=>{
-    if (/.md$/.test(filedir)) {
-        if(hasobj.fileText){
-            let hasHObjs = hasobj;
-            hashElement(filedir).then(res=>{                
-                if(hasHObjs.fileText.indexOf(res.hash)==-1){
-                    //执行写入
-                    //同时更新缓存
-                    fs.writeFileSync(hasHObjs.cachePath,
-                        hasHObjs.fileText+'|'+res.hash
-                        ,'utf-8');
-
-                    fileReadStar(filedir,(obj)=>{
-                        callback(obj)
+          
+    } 
+    checkSelf(){
+        let _that = this;
+        return new Promise((resolve,reject)=>{
+            new contrast({
+                entry:path.join(__dirname,"mdToVue.js"),
+                include:["*.js"]
+            }).run().then(res=>{                
+                if(JSON.stringify(res) != "{}"){
+                    //有变动清除当前entry缓存,重新渲染
+                    rimraf(_that.cachePath,err=>{
+                        console.log(err)
+                        resolve()
                     })
                     })
+                }else{
+                    resolve()
                 }
                 }
             })
             })
-        }else{
-            //如果没有hash 直接做下一部
-            fileReadStar(filedir,(obj)=>{
-                callback(obj)
-            })
-        }
-        //对md文件存储 hash       
-        //文件读取
+        })
         
         
     }
     }
-}
-/**
- * 检查文件是否存折
- * @param {*} path 
- * @param {*} callback 
- */
-function checkIsexists (path,callback){  
-    let pathFileName = path.replace(/[^a-zA-Z]/g,'');
-    let cacheName = './scripts/local'+pathFileName+'.cache';
-    fs.exists(cacheName, res=>{
-        if(!res){
-            fs.writeFile(cacheName,'','utf8',()=>{
-                callback(cacheName)
-            })
-        }else{
-            callback(cacheName)
-        }
-    }) 
-}
-/**
- * 执行文件缓存
- */
-let outhash = [];
-function pushHash(obj){ 
-    //紧紧插入md文件hash                       
-    if(/\.md$/.test(obj.name)&&obj['hash']){
-        outhash.push(obj.hash);
-    }
-    if(obj['children']&&obj['children'].length>0){
-        obj['children'].map(res=>{
-            pushHash(res)
-        })
-    }              
-}
-//hash 对比
-/**
- * 初始化检查是否有md文件 hash
- * 如果没有 hash 创建一个 json文件并把 md文件 hash进去 用来做缓存
- * 初始化获取所有md文件的 hash
- * @param {*} path 
- */
-function comparehash(path,callback){
-    checkIsexists(path,(cachePath)=>{       
-        //获取文件内容
-        let fileText = fs.readFileSync(cachePath,'utf-8');        
-         //获取文件 hash    
-        hashElement(path, {
+    apply(){} 
+    star(){  
+        let _that = this;        
+        hashElement(_that.options.entry, {
             folders: { exclude: ['.*', 'node_modules', 'test_coverage'] },
             folders: { exclude: ['.*', 'node_modules', 'test_coverage'] },
-            files: { include: ['*.md'],exclude:['*.js','*.vue','*.scss','__test__'] }
+            files: { include: ['*.md']},
+            matchBasename: true
         }).then(hash => {           
         }).then(hash => {           
-            if(fileText){
-                //如果有内容
-                callback({
-                    fileText:fileText,
-                    cachePath:cachePath
-                })
-            }else{
-                pushHash(hash)               
-                fs.writeFileSync(cachePath,outhash.join('|'),'utf-8');
-                //如果没有内容
-                callback({
-                    fileText:fileText,
-                    cachePath:cachePath
-                })
-            }
+            nodeFilelist.read([_that.options.entry],{"ext":'md'}, res => {                  
+                res.map(item =>{
+                    let fileSplits = item.path.split(path.sep);
+                    let fileName = fileSplits.pop();
+                    if(_that.isDoc(fileName)){
+                            fileName = fileSplits.pop();
+                    }else{
+                        fileName = fileName.replace(/\.md/,'');
+                    }
+                    if(_that.needHandleFiles[fileName]){                   
+                        _that.read(item.path).then(res=>{
+                            _that.headHandle();
+                            _that.markHandle();
+                            let html = _that.marked(res);                                
+                            _that.write({
+                                outsrc:_that.options.output,
+                                name:fileName + '.vue',
+                                html:html
+                            });
+                        })
+                    }                   
+                });
+            });
         })
         })
-        .catch(error => {
-            return console.error('hashing failed:', error);
-        }); 
-    })     
-}
-//文件监听
-function filelisten(param){  
-    let watcher = Chokidar.watch(param.entry,{
-        persistent: true,
-        usePolling: true,
-    })
-    let log = console.dir.bind(console);
-    let watchAction = function({event, eventPath}){      
-        // 这里进行文件更改后的操作
-        fileReadStar(eventPath,(res)=>{           
-            createdFile(param.output + res.mdName + '.vue', res.html, param)
+    }
+    isDoc(name){
+        return (name == "doc.md") ? true : false;
+    }
+    read(src){
+        return new Promise((resolve,reject)=>{
+            fs.readFile(src, 'utf-8', (err, data) => {               
+                resolve(data)
+            })
         })
         })
     }
     }
-    watcher.on('change', path => watchAction({event: 'change', eventPath: path}))
-    .on('unlink', path => watchAction({event: 'remove', eventPath: path}));
-}
-
-/**
- * 文件转md
- * @param {obj} 
- * @entry {string} 文件读取路径 
- * @output {string} 文件输出路径 
- * @needCode {boolen} 是否需要二维码 默认 true
- */
-function fileDisplay(param) {
-    //检查文件是否第一次初始化并获取hash
-    comparehash(param.entry,(hashMsgObj)=>{ 
-        nodeFilelist.read([param.entry],{"ext":"md"},res=>{    
-            let reslength = res.length;    
-            let routers = [];            
-            res.map((item,index)=>{   //数组化文件   
-                ismd(item.path,hashMsgObj,res=>{
-                    //res md文件处理结果           
-                    createdFile(param.output + res.mdName + '.vue', res.html, param)
-                })
-            })     
+    write(param){
+        let _that = this;
+        return new Promise((resolve,reject)=>{  
+            let outPath = path.join(param.outsrc,param.name);           
+            let contexts = `<template>
+                                <div  @click="dsCode">
+                                <div v-if="content" class="layer">
+                                <pre><span class="close-box" @click="closelayer"></span><div v-html="content"></div></pre>
+                                </div>`+ param.html + (_that.options.hasMarkList ? '<ul class="markList">' + _that.Articlehead + '</ul>' : '')+
+                                `<nut-backtop :right="50" :bottom="50"></nut-backtop>
+                                </div>
+                            </template><script>import root from '../root.js';
+            export default {
+                mixins:[root]
+            }</script>`;    
+            _that.Articlehead = "";
+            _that.Articleheadcount = 0; 
+            fs.writeFile(outPath ,contexts,'utf8',(err,res)=>{ })
         })
         })
-    });  
-}
-
-/**
- * 输出的文件目录 是否存在
- * @outPath {String} 输出的文件目录 
- */
-function ishasOutFile(outPath,callback){
-    fs.stat(outPath,(err,res)=>{       
-        if(err){
-            fs.mkdir(outPath,err=>{
+    }
+    ishasOutFile(outPath){
+        return new Promise((resolve,reject)=>{
+            fs.stat(outPath,(err,res)=>{       
                 if(err){
                 if(err){
-                    console.log(err)
-                }else{                  
-                    callback()
-                }               
-            })
-        }else{
-            callback()
-        }
-    })
-}
-/**
- * 
- * @param {entry} 文件读取路径 
- * @param {output} 文件输出路径 
- * @param {needCode} 是否需要二维码 默认 true
- */
-function MdToHtml(commomOption) {
-    // 默认参数就这么多了,暂时没想到
-    let params = {
-        entry:'',
-        output:'',
-        needCode:true,
-        isbuild:true,
-        hasMarkList:true
+                    fs.mkdir(outPath,err=>{
+                        if(err){
+                            reject(err)
+                        }else{ 
+                            resolve(true)
+                        }               
+                    })
+                }else{                    
+                    resolve(true)
+                }
+            })  
+        })      
+    }
+    headHandle(){
+        let _that = this;
+        let options = _that.options;          
+        _that.rendererMd.heading = function (text,level){           
+            let headcode = '<i class="qrcode"><a :href="demourl"><span>请使用手机扫码体验</span><img :src="codeurl" alt=""></a></i>';              
+            let codeHead = `<h1>` + text +headcode+`</h1>`;
+            let normal = `<h`+level+`>`+text+`</h`+level+`>`;    
+            let Articleheadcounts = null;           
+            if(level==2&&_that.options.hasMarkList){
+                Articleheadcounts = _that.Articleheadcount;
+                Articleheadcounts++;
+                _that.Articleheadcount = Articleheadcounts;
+                let headmsg = _that.Articlehead;
+                headmsg +=`<li @click="leavelchose(`+Articleheadcounts+`)" :class="levalcur==`+Articleheadcounts+`?'cur':''"  class="level`+Articleheadcounts+'"><a href="#head'+Articleheadcounts+'">'+text.substr(0,10)+'</a></li>';
+                _that.Articlehead = headmsg;
+            }    
+            let maskIdHead = "<h"+level+" class='visibility' id='head"+Articleheadcounts+"'>"+ text +"</h"+level+">"; 
+            //判断条件                         
+            if(_that.options.hasMarkList && _that.options.needCode){
+                if(level == 1){
+                    return codeHead;
+                }else if(level == 2){
+                    return maskIdHead;
+                } else{
+                    return normal;
+                }
+            }else if(_that.options.hasMarkList && !_that.options.needCode){
+                if(level !=1){
+                    return maskIdHead;
+                } else{
+                    return normal;
+                }
+            }else if(!_that.options.hasMarkList && _that.options.needCode){
+                if(level == 1){
+                    return codeHead;
+                } else{
+                    return normal;
+                }
+            }else if(!_that.options.hasMarkList && !_that.options.needCode){
+                return normal;
+            }
+        };
+    }
+    codeHandle(){
+        this.rendererMd.code = function (code, infostring, escaped) {
+            var lang = (infostring || '').match(/\S*/)[0];
+            if (this.options.highlight) {
+                var out = this.options.highlight(code, lang);
+                if (out != null && out !== code) {
+                    escaped = true;
+                    code = out;
+                }
+            }
+            if (!lang) {
+                return '<pre><code>'
+                    + (escaped ? code : escape(code, true))
+                    + '</code></pre>';
+            }
+            if (lang === 'html') {
+                code = code.replace(/@latest/g, '@' + version)
+            }
+            return '<hide><pre class="prettyprint"><span class="lang">' + lang + '</span><div class="code-wrapper"><code class="'
+                + this.options.langPrefix
+                + escape(lang, true)
+                + '">'
+                + (escaped ? code : escape(code, true))
+                + '</code></div><i class="copy" copy="copy" data-clipboard-action="copy" data-clipboard-target="code" title="复制代码"></i><i toast="toast" title="全屏"></i></pre></hide>\n';
+        };
+    }
+    markHandle(){
+        let _that = this;
+        this.marked.setOptions({
+            renderer: _that.rendererMd,
+            highlight: function (code) {
+                return require('highlight.js').highlightAuto(code).value;
+            },
+            tables: true
+        });
     }
     }
-    params = Object.assign(params,commomOption);    
-    
-    //检查输出路径
-    ishasOutFile(params.output,()=>{
-         //获取所有的md 转html的结果
-        fileDisplay(params);
-        //文件监听 
-        if(params.isbuild){
-            filelisten(params);
-        }   
-        
-    });
-   
-}
-//用于后期的扩展暂时没想到
-MdToHtml.prototype.apply = function (compiler) {
-    //  console.log(compiler,'lls')
 };
 };
+module.exports = mdVue;
 
 
-module.exports = MdToHtml;