mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-11-12 23:45:18 +01:00
fix old github download repos
This commit is contained in:
6 files changed
+154
-22
No files matched your search
+18
-8
@@ -593,7 +593,9 @@ angular
|
||||
if (dir) {
|
||||
output += `<a ng-click="openFolder('${path}', $event)">${name}</a>`;
|
||||
} else {
|
||||
output += `<a href='/r/${$scope.repoId}${path}'>${name}</a>`;
|
||||
output += `<a href='/r/${$scope.repoId}${encodePathForUrl(
|
||||
path
|
||||
)}'>${name}</a>`;
|
||||
}
|
||||
if (truncated) {
|
||||
output += `<span class="truncated-warning" title="{{ 'WARNINGS.folder_truncated' | translate }}"><i class="fas fa-exclamation-triangle"></i></span>`;
|
||||
@@ -2255,7 +2257,9 @@ angular
|
||||
}
|
||||
|
||||
// redirect to readme
|
||||
$location.url(uri + readmeCandidates[best_match]);
|
||||
$location.url(
|
||||
uri + encodePathForUrl(readmeCandidates[best_match])
|
||||
);
|
||||
}
|
||||
}
|
||||
$scope.getFiles = async function (path) {
|
||||
@@ -2353,11 +2357,15 @@ angular
|
||||
// server returns a fresh ETag on first hit either way.
|
||||
const sha = (fileInfo && fileInfo.sha) || "0";
|
||||
$http
|
||||
.get(`/api/repo/${$scope.repoId}/file/${path}?v=` + sha, {
|
||||
transformResponse: (data) => {
|
||||
return data;
|
||||
},
|
||||
})
|
||||
.get(
|
||||
`/api/repo/${$scope.repoId}/file/${encodePathForUrl(path)}?v=` +
|
||||
sha,
|
||||
{
|
||||
transformResponse: (data) => {
|
||||
return data;
|
||||
},
|
||||
}
|
||||
)
|
||||
.then(
|
||||
(res) => {
|
||||
$scope.type = originalType;
|
||||
@@ -2427,7 +2435,9 @@ angular
|
||||
if ($scope.file && $scope.file.sha) {
|
||||
fileVersion = $scope.file.sha;
|
||||
}
|
||||
$scope.url = `/api/repo/${$scope.repoId}/file/${$scope.filePath}?v=${fileVersion}`;
|
||||
$scope.url = `/api/repo/${$scope.repoId}/file/${encodePathForUrl(
|
||||
$scope.filePath
|
||||
)}?v=${fileVersion}`;
|
||||
|
||||
let extension = $scope.filePath.toLowerCase();
|
||||
const extensionIndex = extension.lastIndexOf(".");
|
||||
|
||||
Vendored
+2
-2
@@ -2621,5 +2621,5 @@ Expecting `+E.join(", ")+", got '"+(this.terminals_[v]||v)+"'":"Parse error on l
|
||||
:root { --mermaid-font-family: ${t.fontFamily}}`),void 0!==t.altFontFamily&&(n+=`
|
||||
:root { --mermaid-alt-font-family: ${t.altFontFamily}}`),i instanceof Map){let e=t.htmlLabels??t.flowchart?.htmlLabels?["> *","span"]:["rect","polygon","ellipse","circle","path"];i.forEach(t=>{gq(t.styles)||e.forEach(e=>{n+=$Fe(t.id,e,t.styles)}),gq(t.textStyles)||(n+=$Fe(t.id,"tspan",(t?.textStyles||[]).map(e=>e.replace("color","fill"))))})}return n},"createCssStyles"),RFe=mt((e,t,i,n)=>{i=LFe(e,i);return uFe(aFe(n+`{${ch(t,i,e.themeVariables)}}`),dFe)},"createUserStyles"),MFe=mt((e="",t,i)=>{let n=e;return i||t||(n=n.replace(/marker-end="url\([\d+./:=?A-Za-z-]*?#/g,'marker-end="url(#')),n=(n=n_(n)).replace(/<br>/g,"<br/>")},"cleanUpSvgCode"),IFe=mt((e="",t)=>{return`<iframe style="width:100%;height:${t?.viewBox?.baseVal?.height?t.viewBox.baseVal.height+"px":"100%"};border:0;margin:0;" src="data:text/html;charset=UTF-8;base64,${SFe(`<body style="margin:0">${e}</body>`)}" sandbox="allow-top-navigation-by-user-activation allow-popups">
|
||||
The "iframe" tag is not supported by your browser.
|
||||
</iframe>`},"putIntoIFrame"),NFe=mt((e,t,i,n,r)=>{var s=e.append("div"),i=(s.attr("id",i),n&&s.attr("style",n),s.append("svg").attr("id",t).attr("width","100%").attr("xmlns","http://www.w3.org/2000/svg"));return r&&i.attr("xmlns:xlink",r),i.append("g"),e},"appendDivSvgG");function DFe(e,t){return e.append("iframe").attr("id",t).attr("style","width: 100%; height: 100%;").attr("sandbox","")}mt(DFe,"sandboxedIframe");var OFe=mt((e,t,i,n)=>{e.getElementById(t)?.remove(),e.getElementById(i)?.remove(),e.getElementById(n)?.remove()},"removeExistingElements"),G=mt(async function(t,i,e){TBe();var n=AFe(i),r=(i=n.code,Ii());I.debug(r),i.length>(r?.maxTextSize??5e4)&&(i="graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa");let s="#"+t,a="i"+t,o="#"+a,l="d"+t,c="#"+l,h=mt(()=>{var e=V(d?o:c).node();e&&"remove"in e&&e.remove()},"removeTempElements"),u=V("body"),d="sandbox"===r.securityLevel,p="loose"===r.securityLevel,g=r.fontFamily;void 0!==e?(e&&(e.innerHTML=""),d?(y=DFe(V(e),a),(u=V(y.nodes()[0].contentDocument.body)).node().style.margin=0):u=V(e),NFe(u,t,l,"font-family: "+g,"http://www.w3.org/1999/xlink")):(OFe(document,t,l,a),d?(y=DFe(V("body"),a),(u=V(y.nodes()[0].contentDocument.body)).node().style.margin=0):u=V("body"),NFe(u,t,l));let f,m;try{f=await fFe.fromText(i,{title:n.title})}catch(e){if(r.suppressErrorRendering)throw h(),e;f=await fFe.fromText("error"),m=e}var e=u.select(c).node(),y=f.type,n=e.firstChild,e=n.firstChild,b=f.renderer.getClasses?.(i,f),b=RFe(r,y,b,s),v=document.createElement("style");v.innerHTML=b,n.insertBefore(v,e);try{await f.renderer.draw(i,t,wye.version,f)}catch(e){throw r.suppressErrorRendering?h():lBe.draw(i,t,wye.version),e}FFe(y,u.select(c+" svg"),f.db.getAccTitle?.(),f.db.getAccDescription?.()),u.select(`[id="${t}"]`).selectAll("foreignobject > *").attr("xmlns","http://www.w3.org/1999/xhtml");let x=u.select(c).node().innerHTML;if(I.debug("config.arrowMarkerAbsolute",r.arrowMarkerAbsolute),x=MFe(x,d,qc(r.arrowMarkerAbsolute)),d?(b=u.select(c+" svg").node(),x=IFe(x,b)):p||(x=Dr.sanitize(x,{ADD_TAGS:CFe,ADD_ATTR:_Fe,HTML_INTEGRATION_POINTS:{foreignobject:!0}})),yFe(),m)throw m;return h(),{diagramType:y,svg:x,bindFunctions:f.db.bindFunctions}},"render");function PFe(e={}){e=at({},e),e?.fontFamily&&!e.themeVariables?.fontFamily&&(e.themeVariables||(e.themeVariables={}),e.themeVariables.fontFamily=e.fontFamily),$i(e),e?.theme&&e.theme in gi?e.themeVariables=gi[e.theme].getThemeVariables(e.themeVariables):e&&(e.themeVariables=gi.default.getThemeVariables(e.themeVariables)),e="object"==typeof e?Ei(e):Ri();T(e.logLevel),TBe()}mt(PFe,"initialize");var BFe=mt((e,t={})=>{e=TFe(e).code;return fFe.fromText(e,t)},"getDiagramFromText");function FFe(e,t,i,n){pFe(t,e),gFe(t,i,n,t.attr("id"))}mt(FFe,"addA11yInfo");var jFe=Object.freeze({render:G,parse:EFe,getDiagramFromText:BFe,initialize:PFe,getConfig:Ii,setConfig:Mi,getSiteConfig:Ri,updateSiteConfig:Li,reset:mt(()=>{Oi()},"reset"),globalReset:mt(()=>{Oi(ki)},"globalReset"),defaultConfig:ki}),zFe=(T(Ii().logLevel),Oi(Ii()),ZK(),s_(),mt((e,t,i)=>{I.warn(e),AC(e)?(i&&i(e.str,e.hash),t.push({...e,message:e.str,error:e})):(i&&i(e),e instanceof Error&&t.push({str:e.message,message:e.message,hash:e.name,error:e}))},"handleError")),UFe=mt(async function(t={querySelector:".mermaid"}){try{await HFe(t)}catch(e){if(AC(e)&&I.error(e.str),JFe.parseError&&JFe.parseError(e),!t.suppressErrors)throw I.error("Use the suppressErrors option to suppress these errors"),e}},"run"),HFe=mt(async function({postRenderCallback:e,querySelector:t,nodes:i}={querySelector:".mermaid"}){var n=jFe.getConfig();I.debug(`${e?"":"No "}Callback function found`);let r;if(i)r=i;else{if(!t)throw new Error("Nodes and querySelector are both undefined");r=document.querySelectorAll(t)}I.debug(`Found ${r.length} diagrams`),void 0!==n?.startOnLoad&&(I.debug("Start On Load: "+n?.startOnLoad),jFe.updateSiteConfig({startOnLoad:n?.startOnLoad}));var s,a=new t_.InitIDGenerator(n.deterministicIds,n.deterministicIDSeed),o=[];for(s of Array.from(r))if(I.info("Rendering diagram: "+s.id),!s.getAttribute("data-processed")){s.setAttribute("data-processed","true");var l="mermaid-"+a.next(),c=s.innerHTML,h=(c=Ve(t_.entityDecode(c)).trim().replace(/<br\s*\/?>/gi,"<br/>"),t_.detectInit(c));h&&I.debug("Detected early reinit: ",h);try{var{svg:u,bindFunctions:d}=await ZFe(l,c,s);s.innerHTML=u,e&&await e(l),d&&d(s)}catch(e){zFe(e,o,JFe.parseError)}}if(0<o.length)throw o[0]},"runThrowsErrors"),qFe=mt(function(e){jFe.initialize(e)},"initialize"),e=mt(async function(e,t,i){I.warn("mermaid.init is deprecated. Please use run instead."),e&&qFe(e);e={postRenderCallback:i,querySelector:".mermaid"};"string"==typeof t?e.querySelector=t:t&&(t instanceof HTMLElement?e.nodes=[t]:e.nodes=t),await UFe(e)},"init"),G=mt(async(e,{lazyLoad:t=!0}={})=>{TBe(),et(...e),!1===t&&await SBe()},"registerExternalDiagrams"),WFe=mt(function(){var e;JFe.startOnLoad&&(e=jFe.getConfig()["startOnLoad"],e)&&JFe.run().catch(e=>I.error
Line truncated
|
||||
`},marked.setOptions({renderer:i,pedantic:!1,gfm:!0,breaks:!1,sanitize:!1,smartLists:!0,smartypants:!1,xhtml:!1,headerIds:!1,katex:katex}),t&&marked.use(baseUrl(t)),marked.use(markedKatex({throwOnError:!1})),marked.use(markedMermaid()),DOMPurify.sanitize(marked.parse(e,{renderer:i}))}angular.module("ngPDFViewer",[]).factory("RecursionHelper",["$compile",function(s){return{compile:function(e,i){angular.isFunction(i)&&(i={post:i});var n,r=e.contents().remove();return{pre:i&&i.pre?i.pre:null,post:function(e,t){(n=n||s(r))(e,function(e){t.append(e)}),i&&i.post&&i.post.apply(null,arguments)}}}}}]).directive("pdfpageviewer",[function(){return{restrict:"E",template:"<canvas></canvas>",scope:{onPageLoad:"=",page:"=",pdfDoc:"="},controller:["$scope","$element",function(n,r){n.scale=1;const s=r.find("canvas")[0];n.$watch("pdfDoc",e=>{e&&n.renderPage(n.page)}),n.renderPage=async function(e){var e=await n.pdfDoc.getPage(e),t=r[0].clientWidth/e.getViewport(1).width,t=e.getViewport(t),i=(s.height=t.height,s.width=t.width,s.getContext("2d"));return await e.render({canvasContext:i,viewport:t}),n.onPageLoad&&n.$apply(function(){n.onPageLoad({page:n.page,total:n.pdfDoc.numPages})}),!0}}]}}]).directive("pdfviewer",["RecursionHelper",function(t){return{restrict:"E",template:"<pdfpageviewer ng-repeat='p in [].constructor(pdfDoc.numPages) track by $index' page='$index + 1' pdf-doc='pdfDoc'></pdfpageviewer>",scope:{onPageLoad:"&",loadProgress:"&",src:"@",id:"="},compile:function(e){return t.compile(e)},controller:["$scope",function(n){n.pdfDoc=null,n.scale=1,n.documentProgress=function(e){n.loadProgress&&n.loadProgress({state:"loading",loaded:e.loaded,total:e.total})},n.loadPDF=function(e){PDFJS.getDocument(e,null,null,n.documentProgress).then(function(e){n.$apply(()=>{n.pdfDoc=e}),n.loadProgress&&n.loadProgress({state:"finished",loaded:0,total:0})},function(e,t){console.log("PDF load error: "+e),n.loadProgress&&n.loadProgress({state:"error",loaded:0,total:0})})},n.$on("pdfviewer.nextPage",function(e,t){null===t&&n.pageNum<n.pdfDoc.numPages&&(n.pageNum++,n.renderPage(n.pageNum))}),n.$on("pdfviewer.prevPage",function(e,t){null===t&&1<n.pageNum&&(n.pageNum--,n.renderPage(n.pageNum))}),n.$on("pdfviewer.gotoPage",function(e,t,i){null===t&&1<=i&&i<=n.pdfDoc.numPages&&(n.pageNum=i,n.renderPage(n.pageNum))}),n.$watch("src",()=>{n.loadPDF(n.src)})}]}}]).service("PDFViewerService",["$rootScope",function(i){var e={nextPage:function(){i.$broadcast("pdfviewer.nextPage")},prevPage:function(){i.$broadcast("pdfviewer.prevPage")},Instance:function(e){var t=e;return{prevPage:function(){i.$broadcast("pdfviewer.prevPage",t)},nextPage:function(){i.$broadcast("pdfviewer.nextPage",t)},gotoPage:function(e){i.$broadcast("pdfviewer.gotoPage",t,e)}}}};return e}]),angular.module("anonymous-github",["ngRoute","ngSanitize","ui.ace","ngPDFViewer","pascalprecht.translate","admin"]).config(["$routeProvider","$locationProvider","$translateProvider",function(e,t,i){i.useStaticFilesLoader({prefix:"/i18n/locale-",suffix:".json"}),i.preferredLanguage("en"),e.when("/",{templateUrl:"/partials/home.htm",controller:"homeController",title:"Anonymous GitHub – Share the code, not the author"}).when("/dashboard",{templateUrl:"/partials/dashboard.htm",controller:"unifiedDashboardController",title:"Your anonymizations – Anonymous GitHub"}).when("/pr-dashboard",{redirectTo:"/dashboard"}).when("/anonymize/:repoId?",{templateUrl:"/partials/anonymize.htm",controller:"anonymizeController",title:"New anonymization – Anonymous GitHub"}).when("/pull-request-anonymize/:pullRequestId?",{templateUrl:"/partials/anonymize.htm",controller:"anonymizeController",title:"Anonymize a pull request – Anonymous GitHub"}).when("/gist-anonymize/:gistId?",{templateUrl:"/partials/anonymize.htm",controller:"anonymizeController",title:"Anonymize a gist – Anonymous GitHub"}).when("/status/:repoId",{templateUrl:"/partials/status.htm",controller:"statusController",title:"Repository status – Anonymous GitHub"}).when("/conferences",{templateUrl:"/partials/conferences.htm",controller:"conferencesController",title:"Your conferences – Anonymous GitHub"}).when("/conference/new",{templateUrl:"/partials/newConference.htm",controller:"newConferenceController",title:"New conference – Anonymous GitHub"}).when("/conference/:conferenceId/edit",{templateUrl:"/partials/newConference.htm",controller:"newConferenceController",title:"Edit conference – Anonymous GitHub"}).when("/conference/:conferenceId",{templateUrl:"/partials/conference.htm",controller:"conferenceController",title:"Conference – Anonymous GitHub"}).when("/faq",{templateUrl:"/partials/faq.htm",controller:"faqController",title:"FAQ – Anonymous GitHub"}).when("/profile",{templateUrl:"/partials/profile.htm",controller:"profileController",title:"Your settings – Anonymous GitHub"}).when("/claim",{templateUrl:"/partials/claim.htm",controller:"claimController",title:"Claim an anonymization – Anonymous GitHub"}).when("/pr/:pullRequestId",{
Line truncated
|
||||
</iframe>`},"putIntoIFrame"),NFe=mt((e,t,i,n,r)=>{var s=e.append("div"),i=(s.attr("id",i),n&&s.attr("style",n),s.append("svg").attr("id",t).attr("width","100%").attr("xmlns","http://www.w3.org/2000/svg"));return r&&i.attr("xmlns:xlink",r),i.append("g"),e},"appendDivSvgG");function DFe(e,t){return e.append("iframe").attr("id",t).attr("style","width: 100%; height: 100%;").attr("sandbox","")}mt(DFe,"sandboxedIframe");var OFe=mt((e,t,i,n)=>{e.getElementById(t)?.remove(),e.getElementById(i)?.remove(),e.getElementById(n)?.remove()},"removeExistingElements"),G=mt(async function(t,i,e){TBe();var n=AFe(i),r=(i=n.code,Ii());I.debug(r),i.length>(r?.maxTextSize??5e4)&&(i="graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa");let s="#"+t,a="i"+t,o="#"+a,l="d"+t,c="#"+l,h=mt(()=>{var e=V(d?o:c).node();e&&"remove"in e&&e.remove()},"removeTempElements"),u=V("body"),d="sandbox"===r.securityLevel,p="loose"===r.securityLevel,g=r.fontFamily;void 0!==e?(e&&(e.innerHTML=""),d?(y=DFe(V(e),a),(u=V(y.nodes()[0].contentDocument.body)).node().style.margin=0):u=V(e),NFe(u,t,l,"font-family: "+g,"http://www.w3.org/1999/xlink")):(OFe(document,t,l,a),d?(y=DFe(V("body"),a),(u=V(y.nodes()[0].contentDocument.body)).node().style.margin=0):u=V("body"),NFe(u,t,l));let f,m;try{f=await fFe.fromText(i,{title:n.title})}catch(e){if(r.suppressErrorRendering)throw h(),e;f=await fFe.fromText("error"),m=e}var e=u.select(c).node(),y=f.type,n=e.firstChild,e=n.firstChild,b=f.renderer.getClasses?.(i,f),b=RFe(r,y,b,s),v=document.createElement("style");v.innerHTML=b,n.insertBefore(v,e);try{await f.renderer.draw(i,t,wye.version,f)}catch(e){throw r.suppressErrorRendering?h():lBe.draw(i,t,wye.version),e}FFe(y,u.select(c+" svg"),f.db.getAccTitle?.(),f.db.getAccDescription?.()),u.select(`[id="${t}"]`).selectAll("foreignobject > *").attr("xmlns","http://www.w3.org/1999/xhtml");let x=u.select(c).node().innerHTML;if(I.debug("config.arrowMarkerAbsolute",r.arrowMarkerAbsolute),x=MFe(x,d,qc(r.arrowMarkerAbsolute)),d?(b=u.select(c+" svg").node(),x=IFe(x,b)):p||(x=Dr.sanitize(x,{ADD_TAGS:CFe,ADD_ATTR:_Fe,HTML_INTEGRATION_POINTS:{foreignobject:!0}})),yFe(),m)throw m;return h(),{diagramType:y,svg:x,bindFunctions:f.db.bindFunctions}},"render");function PFe(e={}){e=at({},e),e?.fontFamily&&!e.themeVariables?.fontFamily&&(e.themeVariables||(e.themeVariables={}),e.themeVariables.fontFamily=e.fontFamily),$i(e),e?.theme&&e.theme in gi?e.themeVariables=gi[e.theme].getThemeVariables(e.themeVariables):e&&(e.themeVariables=gi.default.getThemeVariables(e.themeVariables)),e="object"==typeof e?Ei(e):Ri();T(e.logLevel),TBe()}mt(PFe,"initialize");var BFe=mt((e,t={})=>{e=TFe(e).code;return fFe.fromText(e,t)},"getDiagramFromText");function FFe(e,t,i,n){pFe(t,e),gFe(t,i,n,t.attr("id"))}mt(FFe,"addA11yInfo");var jFe=Object.freeze({render:G,parse:EFe,getDiagramFromText:BFe,initialize:PFe,getConfig:Ii,setConfig:Mi,getSiteConfig:Ri,updateSiteConfig:Li,reset:mt(()=>{Oi()},"reset"),globalReset:mt(()=>{Oi(ki)},"globalReset"),defaultConfig:ki}),zFe=(T(Ii().logLevel),Oi(Ii()),ZK(),s_(),mt((e,t,i)=>{I.warn(e),AC(e)?(i&&i(e.str,e.hash),t.push({...e,message:e.str,error:e})):(i&&i(e),e instanceof Error&&t.push({str:e.message,message:e.message,hash:e.name,error:e}))},"handleError")),UFe=mt(async function(t={querySelector:".mermaid"}){try{await HFe(t)}catch(e){if(AC(e)&&I.error(e.str),JFe.parseError&&JFe.parseError(e),!t.suppressErrors)throw I.error("Use the suppressErrors option to suppress these errors"),e}},"run"),HFe=mt(async function({postRenderCallback:e,querySelector:t,nodes:i}={querySelector:".mermaid"}){var n=jFe.getConfig();I.debug(`${e?"":"No "}Callback function found`);let r;if(i)r=i;else{if(!t)throw new Error("Nodes and querySelector are both undefined");r=document.querySelectorAll(t)}I.debug(`Found ${r.length} diagrams`),void 0!==n?.startOnLoad&&(I.debug("Start On Load: "+n?.startOnLoad),jFe.updateSiteConfig({startOnLoad:n?.startOnLoad}));var s,a=new t_.InitIDGenerator(n.deterministicIds,n.deterministicIDSeed),o=[];for(s of Array.from(r))if(I.info("Rendering diagram: "+s.id),!s.getAttribute("data-processed")){s.setAttribute("data-processed","true");var l="mermaid-"+a.next(),c=s.innerHTML,h=(c=Ve(t_.entityDecode(c)).trim().replace(/<br\s*\/?>/gi,"<br/>"),t_.detectInit(c));h&&I.debug("Detected early reinit: ",h);try{var{svg:u,bindFunctions:d}=await ZFe(l,c,s);s.innerHTML=u,e&&await e(l),d&&d(s)}catch(e){zFe(e,o,JFe.parseError)}}if(0<o.length)throw o[0]},"runThrowsErrors"),qFe=mt(function(e){jFe.initialize(e)},"initialize"),e=mt(async function(e,t,i){I.warn("mermaid.init is deprecated. Please use run instead."),e&&qFe(e);e={postRenderCallback:i,querySelector:".mermaid"};"string"==typeof t?e.querySelector=t:t&&(t instanceof HTMLElement?e.nodes=[t]:e.nodes=t),await UFe(e)},"init"),G=mt(async(e,{lazyLoad:t=!0}={})=>{TBe(),et(...e),!1===t&&await SBe()},"registerExternalDiagrams"),WFe=mt(function(){var e;JFe.startOnLoad&&(e=jFe.getConfig()["startOnLoad"],e)&&JFe.run().catch(e=>I.error
Line truncated
|
||||
`},marked.setOptions({renderer:i,pedantic:!1,gfm:!0,breaks:!1,sanitize:!1,smartLists:!0,smartypants:!1,xhtml:!1,headerIds:!1,katex:katex}),t&&marked.use(baseUrl(t)),marked.use(markedKatex({throwOnError:!1})),marked.use(markedMermaid()),DOMPurify.sanitize(marked.parse(e,{renderer:i}))}angular.module("ngPDFViewer",[]).factory("RecursionHelper",["$compile",function(s){return{compile:function(e,i){angular.isFunction(i)&&(i={post:i});var n,r=e.contents().remove();return{pre:i&&i.pre?i.pre:null,post:function(e,t){(n=n||s(r))(e,function(e){t.append(e)}),i&&i.post&&i.post.apply(null,arguments)}}}}}]).directive("pdfpageviewer",[function(){return{restrict:"E",template:"<canvas></canvas>",scope:{onPageLoad:"=",page:"=",pdfDoc:"="},controller:["$scope","$element",function(n,r){n.scale=1;const s=r.find("canvas")[0];n.$watch("pdfDoc",e=>{e&&n.renderPage(n.page)}),n.renderPage=async function(e){var e=await n.pdfDoc.getPage(e),t=r[0].clientWidth/e.getViewport(1).width,t=e.getViewport(t),i=(s.height=t.height,s.width=t.width,s.getContext("2d"));return await e.render({canvasContext:i,viewport:t}),n.onPageLoad&&n.$apply(function(){n.onPageLoad({page:n.page,total:n.pdfDoc.numPages})}),!0}}]}}]).directive("pdfviewer",["RecursionHelper",function(t){return{restrict:"E",template:"<pdfpageviewer ng-repeat='p in [].constructor(pdfDoc.numPages) track by $index' page='$index + 1' pdf-doc='pdfDoc'></pdfpageviewer>",scope:{onPageLoad:"&",loadProgress:"&",src:"@",id:"="},compile:function(e){return t.compile(e)},controller:["$scope",function(n){n.pdfDoc=null,n.scale=1,n.documentProgress=function(e){n.loadProgress&&n.loadProgress({state:"loading",loaded:e.loaded,total:e.total})},n.loadPDF=function(e){PDFJS.getDocument(e,null,null,n.documentProgress).then(function(e){n.$apply(()=>{n.pdfDoc=e}),n.loadProgress&&n.loadProgress({state:"finished",loaded:0,total:0})},function(e,t){console.log("PDF load error: "+e),n.loadProgress&&n.loadProgress({state:"error",loaded:0,total:0})})},n.$on("pdfviewer.nextPage",function(e,t){null===t&&n.pageNum<n.pdfDoc.numPages&&(n.pageNum++,n.renderPage(n.pageNum))}),n.$on("pdfviewer.prevPage",function(e,t){null===t&&1<n.pageNum&&(n.pageNum--,n.renderPage(n.pageNum))}),n.$on("pdfviewer.gotoPage",function(e,t,i){null===t&&1<=i&&i<=n.pdfDoc.numPages&&(n.pageNum=i,n.renderPage(n.pageNum))}),n.$watch("src",()=>{n.loadPDF(n.src)})}]}}]).service("PDFViewerService",["$rootScope",function(i){var e={nextPage:function(){i.$broadcast("pdfviewer.nextPage")},prevPage:function(){i.$broadcast("pdfviewer.prevPage")},Instance:function(e){var t=e;return{prevPage:function(){i.$broadcast("pdfviewer.prevPage",t)},nextPage:function(){i.$broadcast("pdfviewer.nextPage",t)},gotoPage:function(e){i.$broadcast("pdfviewer.gotoPage",t,e)}}}};return e}]),angular.module("anonymous-github",["ngRoute","ngSanitize","ui.ace","ngPDFViewer","pascalprecht.translate","admin"]).config(["$routeProvider","$locationProvider","$translateProvider",function(e,t,i){i.useStaticFilesLoader({prefix:"/i18n/locale-",suffix:".json"}),i.preferredLanguage("en"),e.when("/",{templateUrl:"/partials/home.htm",controller:"homeController",title:"Anonymous GitHub – Share the code, not the author"}).when("/dashboard",{templateUrl:"/partials/dashboard.htm",controller:"unifiedDashboardController",title:"Your anonymizations – Anonymous GitHub"}).when("/pr-dashboard",{redirectTo:"/dashboard"}).when("/anonymize/:repoId?",{templateUrl:"/partials/anonymize.htm",controller:"anonymizeController",title:"New anonymization – Anonymous GitHub"}).when("/pull-request-anonymize/:pullRequestId?",{templateUrl:"/partials/anonymize.htm",controller:"anonymizeController",title:"Anonymize a pull request – Anonymous GitHub"}).when("/gist-anonymize/:gistId?",{templateUrl:"/partials/anonymize.htm",controller:"anonymizeController",title:"Anonymize a gist – Anonymous GitHub"}).when("/status/:repoId",{templateUrl:"/partials/status.htm",controller:"statusController",title:"Repository status – Anonymous GitHub"}).when("/conferences",{templateUrl:"/partials/conferences.htm",controller:"conferencesController",title:"Your conferences – Anonymous GitHub"}).when("/conference/new",{templateUrl:"/partials/newConference.htm",controller:"newConferenceController",title:"New conference – Anonymous GitHub"}).when("/conference/:conferenceId/edit",{templateUrl:"/partials/newConference.htm",controller:"newConferenceController",title:"Edit conference – Anonymous GitHub"}).when("/conference/:conferenceId",{templateUrl:"/partials/conference.htm",controller:"conferenceController",title:"Conference – Anonymous GitHub"}).when("/faq",{templateUrl:"/partials/faq.htm",controller:"faqController",title:"FAQ – Anonymous GitHub"}).when("/profile",{templateUrl:"/partials/profile.htm",controller:"profileController",title:"Your settings – Anonymous GitHub"}).when("/claim",{templateUrl:"/partials/claim.htm",controller:"claimController",title:"Claim an anonymization – Anonymous GitHub"}).when("/pr/:pullRequestId",{
Line truncated
|
||||
@@ -15,6 +15,13 @@ function saveFilterPrefs(key, value) {
|
||||
}
|
||||
}
|
||||
|
||||
function encodePathForUrl(path) {
|
||||
return String(path || "")
|
||||
.split("/")
|
||||
.map((segment) => encodeURIComponent(segment))
|
||||
.join("/");
|
||||
}
|
||||
|
||||
function humanFileSize(bytes, si = false, dp = 1) {
|
||||
const thresh = si ? 1000 : 1024;
|
||||
|
||||
|
||||
+15
-1
@@ -141,7 +141,21 @@ export default class Repository {
|
||||
force: false,
|
||||
}
|
||||
): Promise<IFile[]> {
|
||||
const hasFile = await FileModel.exists({ repoId: this.repoId }).exec();
|
||||
let hasFile = await FileModel.exists({ repoId: this.repoId }).exec();
|
||||
// Files created by GitHubDownload don't carry a valid 40-char GitHub
|
||||
// blob SHA. When the source type later switches to GitHubStream the
|
||||
// stale entries cause blob-API 404s. Detect this by sampling a file
|
||||
// with a sha and checking its length; force a re-fetch if it doesn't
|
||||
// look like a GitHub SHA.
|
||||
if (hasFile && this.source instanceof GitHubStream) {
|
||||
const sample = await FileModel.findOne(
|
||||
{ repoId: this.repoId, sha: { $exists: true, $ne: null } },
|
||||
{ sha: 1 }
|
||||
).exec();
|
||||
if (sample?.sha && sample.sha.length !== 40) {
|
||||
hasFile = null;
|
||||
}
|
||||
}
|
||||
if (!hasFile || opt.force) {
|
||||
await FileModel.deleteMany({ repoId: this.repoId }).exec();
|
||||
const files = await this.source.getFiles(opt.progress);
|
||||
|
||||
@@ -20,6 +20,21 @@ import config from "../../config";
|
||||
|
||||
const logger = createLogger("gh-stream");
|
||||
|
||||
export function githubRawFileUrl(
|
||||
owner: string,
|
||||
repo: string,
|
||||
commit: string,
|
||||
filePath: string
|
||||
): string {
|
||||
const encodedPath = filePath
|
||||
.split("/")
|
||||
.map((segment) => encodeURIComponent(segment))
|
||||
.join("/");
|
||||
return `https://github.com/${encodeURIComponent(owner)}/${encodeURIComponent(
|
||||
repo
|
||||
)}/raw/${encodeURIComponent(commit)}/${encodedPath}`;
|
||||
}
|
||||
|
||||
export default class GitHubStream extends GitHubBase {
|
||||
type: "GitHubDownload" | "GitHubStream" | "Zip" = "GitHubStream";
|
||||
|
||||
@@ -64,7 +79,12 @@ export default class GitHubStream extends GitHubBase {
|
||||
// blob endpoint above returns the raw pointer text instead, so we use this
|
||||
// as the fallback for LFS files (#95).
|
||||
private downloadFileViaRaw(token: string, filePath: string) {
|
||||
const url = `https://github.com/${this.data.organization}/${this.data.repoName}/raw/${this.data.commit}/${filePath}`;
|
||||
const url = githubRawFileUrl(
|
||||
this.data.organization,
|
||||
this.data.repoName,
|
||||
this.data.commit,
|
||||
filePath
|
||||
);
|
||||
logger.debug("downloading via raw URL (LFS)", { url });
|
||||
return got.stream(url, {
|
||||
headers: { authorization: `token ${token}` },
|
||||
@@ -72,6 +92,58 @@ export default class GitHubStream extends GitHubBase {
|
||||
});
|
||||
}
|
||||
|
||||
// Try the blob API, then fall back to the raw URL on statuses where the
|
||||
// path-based endpoint can still succeed. 422 is the blob endpoint's size
|
||||
// cap; 404 can happen with stale/invalid blob SHAs while the path still
|
||||
// exists at the requested commit.
|
||||
private downloadWithFallback(
|
||||
token: string,
|
||||
sha: string,
|
||||
filePath: string
|
||||
): Promise<stream.Readable> {
|
||||
return new Promise<stream.Readable>((resolve) => {
|
||||
const blobStream = this.downloadFile(token, sha);
|
||||
let settled = false;
|
||||
|
||||
const fallbackStatuses = new Set([404, 422]);
|
||||
const fallbackToRaw = (statusCode?: number) => {
|
||||
settled = true;
|
||||
logger.info("blob API failed, falling back to raw URL", {
|
||||
filePath,
|
||||
statusCode,
|
||||
});
|
||||
resolve(this.downloadFileViaRaw(token, filePath));
|
||||
};
|
||||
|
||||
blobStream.on("error", (err) => {
|
||||
if (settled) return;
|
||||
const statusCode = (
|
||||
err as { response?: { statusCode?: number } }
|
||||
)?.response?.statusCode;
|
||||
if (statusCode && fallbackStatuses.has(statusCode)) {
|
||||
fallbackToRaw(statusCode);
|
||||
return;
|
||||
}
|
||||
// Other errors: let the normal pipeline handle them.
|
||||
settled = true;
|
||||
const passthrough = new stream.PassThrough();
|
||||
passthrough.destroy(err);
|
||||
resolve(passthrough);
|
||||
});
|
||||
|
||||
blobStream.on("response", (response) => {
|
||||
if (settled) return;
|
||||
if (fallbackStatuses.has(response.statusCode || 0)) {
|
||||
blobStream.destroy();
|
||||
fallbackToRaw(response.statusCode);
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
resolve(this.resolveLfsPointer(blobStream, token, filePath));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Wrap a blob stream so that if its first ~150 bytes look like a Git LFS
|
||||
// pointer, the bytes are dropped and replaced by a fresh fetch from the
|
||||
// raw URL endpoint (which resolves LFS automatically). Non-LFS files are
|
||||
@@ -190,11 +262,14 @@ export default class GitHubStream extends GitHubBase {
|
||||
});
|
||||
}
|
||||
const token = await this.data.getToken();
|
||||
const blobStream = this.downloadFile(token, expected.sha);
|
||||
// If the blob is a Git LFS pointer, swap to a raw-URL fetch so the
|
||||
// file content (not the pointer text) makes it into the pipeline. See
|
||||
// #95 — Support for Git LFS.
|
||||
const content = this.resolveLfsPointer(blobStream, token, filePath);
|
||||
|
||||
// Try the blob API first, but fall back to the raw URL on recoverable
|
||||
// blob misses/caps while still preserving LFS pointer handling.
|
||||
const content = await this.downloadWithFallback(
|
||||
token,
|
||||
expected.sha,
|
||||
filePath
|
||||
);
|
||||
|
||||
// duplicate the stream to write it to the storage
|
||||
const stream1 = content.pipe(new stream.PassThrough());
|
||||
|
||||
@@ -6,14 +6,40 @@ import { fileETag } from "./file-etag";
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
function decodePathSegment(segment: string): string {
|
||||
try {
|
||||
return decodeURIComponent(segment);
|
||||
} catch {
|
||||
try {
|
||||
return decodeURI(segment);
|
||||
} catch {
|
||||
return segment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function filePathFromRequestUrl(
|
||||
reqUrl: string,
|
||||
protocol: string,
|
||||
hostname: string,
|
||||
repoId: string
|
||||
): string {
|
||||
const pathname = new URL(reqUrl, `${protocol}://${hostname}`).pathname;
|
||||
const prefix = `/${encodeURIComponent(repoId)}/file/`;
|
||||
const rawPath = pathname.startsWith(prefix)
|
||||
? pathname.substring(prefix.length)
|
||||
: pathname.replace(`/${repoId}/file/`, "");
|
||||
return rawPath.split("/").map(decodePathSegment).join("/");
|
||||
}
|
||||
|
||||
router.get(
|
||||
"/:repoId/file/:path*",
|
||||
async (req: express.Request, res: express.Response) => {
|
||||
const anonymizedPath = decodeURI(
|
||||
new URL(req.url, `${req.protocol}://${req.hostname}`).pathname.replace(
|
||||
`/${req.params.repoId}/file/`,
|
||||
""
|
||||
)
|
||||
const anonymizedPath = filePathFromRequestUrl(
|
||||
req.url,
|
||||
req.protocol,
|
||||
req.hostname,
|
||||
req.params.repoId
|
||||
);
|
||||
if (anonymizedPath.endsWith("/")) {
|
||||
return handleError(
|
||||
|
||||
Reference in new issue
Block a user