-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathindex.js
More file actions
2 lines (2 loc) · 2.71 KB
/
index.js
File metadata and controls
2 lines (2 loc) · 2.71 KB
1
2
module.exports=n=>{if(!n)return[];if(typeof n!="string"||n.match(/^\s+$/))return[];const s=n.split(`
`);if(s.length===0)return[];const a=[];let o=null,d=null,u=0,m=0,l=null;const g=e=>{d?.changes.push({type:"normal",normal:!0,ln1:u++,ln2:m++,content:e}),l.oldLines--,l.newLines--},p=e=>{const[t,r]=parseFiles(e)??[];o={chunks:[],deletions:0,additions:0,from:t,to:r},a.push(o)},i=()=>{(!o||o.chunks.length)&&p()},$=(e,t)=>{i(),o.new=!0,o.newMode=t[1],o.from="/dev/null"},N=(e,t)=>{i(),o.deleted=!0,o.oldMode=t[1],o.to="/dev/null"},x=(e,t)=>{i(),o.oldMode=t[1]},F=(e,t)=>{i(),o.newMode=t[1]},S=(e,t)=>{i(),o.index=e.split(" ").slice(1),t[1]&&(o.oldMode=o.newMode=t[1].trim())},k=e=>{i(),o.from=parseOldOrNewFile(e)},y=e=>{i(),o.to=parseOldOrNewFile(e)},f=e=>+(e||1),M=(e,t)=>{o||p(e);const[r,c,w,L]=t.slice(1);u=+r,m=+w,d={content:e,changes:[],oldStart:+r,oldLines:f(c),newStart:+w,newLines:f(L)},l={oldLines:f(c),newLines:f(L)},o.chunks.push(d)},R=e=>{d&&(d.changes.push({type:"del",del:!0,ln:u++,content:e}),o.deletions++,l.oldLines--)},b=e=>{d&&(d.changes.push({type:"add",add:!0,ln:m++,content:e}),o.additions++,l.newLines--)},h=e=>{if(!d)return;const[t]=d.changes.slice(-1);d.changes.push({type:t.type,[t.type]:!0,ln1:t.ln1,ln2:t.ln2,ln:t.ln,content:e})},_=[[/^diff\s/,p],[/^new file mode (\d+)$/,$],[/^deleted file mode (\d+)$/,N],[/^old mode (\d+)$/,x],[/^new mode (\d+)$/,F],[/^index\s[\da-zA-Z]+\.\.[\da-zA-Z]+(\s(\d+))?$/,S],[/^---\s/,k],[/^\+\+\+\s/,y],[/^@@\s+-(\d+),?(\d+)?\s+\+(\d+),?(\d+)?\s@@/,M],[/^\\ No newline at end of file$/,h]],v=[[/^\\ No newline at end of file$/,h],[/^-/,R],[/^\+/,b],[/^\s*/,g]],C=e=>{for(const[t,r]of v){const c=e.match(t);if(c){r(e,c);break}}l.oldLines===0&&l.newLines===0&&(l=null)},H=e=>{for(const[t,r]of _){const c=e.match(t);if(c){r(e,c);break}}},O=e=>{l?C(e):H(e)};for(const e of s)O(e);return a};const fileNameDiffRegex=/(a|i|w|c|o|1|2)\/.*(?=["']? ["']?(b|i|w|c|o|1|2)\/)|(b|i|w|c|o|1|2)\/.*$/g,gitFileHeaderRegex=/^(a|b|i|w|c|o|1|2)\//,parseFiles=n=>n?.match(fileNameDiffRegex)?.map(a=>a.replace(gitFileHeaderRegex,"").replace(/("|')$/,"")),qoutedFileNameRegex=/^\\?['"]|\\?['"]$/g,parseOldOrNewFile=n=>{let s=leftTrimChars(n,"-+").trim();return s=removeTimeStamp(s),s.replace(qoutedFileNameRegex,"").replace(gitFileHeaderRegex,"")},leftTrimChars=(n,s)=>{if(n=makeString(n),!s&&String.prototype.trimLeft)return n.trimLeft();const a=formTrimmingString(s);return n.replace(new RegExp(`^${a}+`),"")},timeStampRegex=/\t.*|\d{4}-\d\d-\d\d\s\d\d:\d\d:\d\d(.\d+)?\s(\+|-)\d\d\d\d/,removeTimeStamp=n=>{const s=timeStampRegex.exec(n);return s&&(n=n.substring(0,s.index).trim()),n},formTrimmingString=n=>n==null?"\\s":n instanceof RegExp?n.source:`[${makeString(n).replace(/([.*+?^=!:${}()|[\]/\\])/g,"\\$1")}]`,makeString=n=>`${n??""}`;