Code EOL. Docs genesis.
|
@ -5,7 +5,7 @@
|
|||
|
||||
### General Support
|
||||
|
||||
If you have general questions about GitPitch that are not answered by the [GitPitch How-To Wiki](https://github.com/gitpitch/gitpitch/wiki) then the best way to ask those questions is by [sending me a tweet](https://twitter.com/gitpitch) on Twitter. Otherwise [open a new issue](https://github.com/gitpitch/gitpitch/issues) on GitHub.
|
||||
If you have general questions about GitPitch that are not answered by the [GitPitch Docs](https://docs.gitpitch.com) then the best way to ask those questions is by [sending me a tweet](https://twitter.com/gitpitch) on Twitter. Otherwise [open a new issue](https://github.com/gitpitch/gitpitch/issues) on GitHub.
|
||||
|
||||
|
||||
### Bug Reports
|
||||
|
|
21
LICENSE.txt
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2016 David Russell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
import com.gitpitch.factory.MarkdownModelFactory;
|
||||
import com.gitpitch.git.*;
|
||||
import com.gitpitch.git.vendors.*;
|
||||
import com.gitpitch.models.Markdown;
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.services.*;
|
||||
import com.gitpitch.policies.CacheTimeout;
|
||||
import com.gitpitch.policies.Dependencies;
|
||||
import com.gitpitch.policies.Runtime;
|
||||
import com.gitpitch.executors.FrontEndThreads;
|
||||
import com.gitpitch.executors.BackEndThreads;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
|
||||
/*
|
||||
* Guice DI injection dependencies for the GitPitch server.
|
||||
*/
|
||||
public class Module extends AbstractModule {
|
||||
|
||||
@Override
|
||||
public void configure() {
|
||||
bind(DiskService.class).asEagerSingleton();
|
||||
bind(GitService.class).asEagerSingleton();
|
||||
bind(PitchService.class).asEagerSingleton();
|
||||
bind(PrintService.class).asEagerSingleton();
|
||||
bind(OfflineService.class).asEagerSingleton();
|
||||
bind(ShellService.class).asEagerSingleton();
|
||||
bind(ImageService.class).asEagerSingleton();
|
||||
bind(VideoService.class).asEagerSingleton();
|
||||
bind(GISTService.class).asEagerSingleton();
|
||||
bind(CodeService.class).asEagerSingleton();
|
||||
bind(SlideService.class).asEagerSingleton();
|
||||
bind(ShortcutsService.class).asEagerSingleton();
|
||||
bind(WebService.class).asEagerSingleton();
|
||||
bind(ComposableService.class).asEagerSingleton();
|
||||
bind(GRSManager.class).asEagerSingleton();
|
||||
bind(GitHub.class).asEagerSingleton();
|
||||
bind(GitLab.class).asEagerSingleton();
|
||||
bind(BitBucket.class).asEagerSingleton();
|
||||
bind(Gitea.class).asEagerSingleton();
|
||||
bind(Gogs.class).asEagerSingleton();
|
||||
bind(GitBucket.class).asEagerSingleton();
|
||||
bind(FrontEndThreads.class).asEagerSingleton();
|
||||
bind(BackEndThreads.class).asEagerSingleton();
|
||||
bind(Dependencies.class).asEagerSingleton();
|
||||
bind(CacheTimeout.class).asEagerSingleton();
|
||||
bind(Runtime.class).asEagerSingleton();
|
||||
install(new FactoryModuleBuilder().implement(Markdown.class, MarkdownModel.class)
|
||||
.build(MarkdownModelFactory.class));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,515 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.controllers;
|
||||
|
||||
import com.gitpitch.git.GRS;
|
||||
import com.gitpitch.git.GRSManager;
|
||||
import com.gitpitch.models.GitRepoModel;
|
||||
import com.gitpitch.models.Markdown;
|
||||
import com.gitpitch.executors.FrontEndThreads;
|
||||
import com.gitpitch.models.SlideshowModel;
|
||||
import com.gitpitch.services.PitchService;
|
||||
import com.gitpitch.oembed.PitchEmbed;
|
||||
import com.gitpitch.policies.Dependencies;
|
||||
import com.gitpitch.policies.Runtime;
|
||||
import com.gitpitch.utils.GitRepoRenderer;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.utils.RFE;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
import play.libs.Json;
|
||||
import play.libs.ws.*;
|
||||
import play.mvc.*;
|
||||
import views.html.*;
|
||||
|
||||
import javax.inject.*;
|
||||
import java.io.File;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
|
||||
/**
|
||||
* Front controller for GitPitch service.
|
||||
*/
|
||||
public class PitchController extends Controller {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final PitchService pitchService;
|
||||
private final FrontEndThreads frontEndThreads;
|
||||
private final Dependencies deps;
|
||||
private final Runtime runtime;
|
||||
private final GRSManager grsManager;
|
||||
|
||||
@Inject
|
||||
public PitchController(PitchService pitchService,
|
||||
FrontEndThreads frontEndThreads,
|
||||
Dependencies deps,
|
||||
Runtime runtime,
|
||||
GRSManager grsManager) {
|
||||
|
||||
this.pitchService = pitchService;
|
||||
this.frontEndThreads = frontEndThreads;
|
||||
this.deps = deps;
|
||||
this.runtime = runtime;
|
||||
this.grsManager = grsManager;
|
||||
}
|
||||
|
||||
/*
|
||||
* Catchall redirects any URL with a trailing slash to the
|
||||
* URL minus the trailing slash. Any remaining unhandled URLs
|
||||
* are redirected to the GitPitch website.
|
||||
*/
|
||||
public Result catchall(String path) {
|
||||
try {
|
||||
if (path != "/" && path.endsWith("/")) {
|
||||
return redirect("/" + path.substring(0, path.length()-1));
|
||||
} else {
|
||||
return ok(com.gitpitch.views.html.NotFound.render());
|
||||
}
|
||||
} catch(Exception ex) {
|
||||
return ok(com.gitpitch.views.html.NotFound.render());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Slideshow builds and renders a GitPitch presentation.
|
||||
*/
|
||||
public CompletionStage<Result> slideshow(String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String grs,
|
||||
String theme,
|
||||
String pitchme,
|
||||
String notes,
|
||||
String offline,
|
||||
String fragments,
|
||||
String webprint) {
|
||||
|
||||
PitchParams pp =
|
||||
PitchParams.build(grsOnCall(grs),
|
||||
user, repo, branch, theme, pitchme, notes);
|
||||
boolean isOffline =
|
||||
(offline == null) ? false : Boolean.parseBoolean(offline);
|
||||
boolean serverPrinting =
|
||||
(fragments == null) ? false : !Boolean.parseBoolean(fragments);
|
||||
boolean webPrinting =
|
||||
(webprint == null) ? false : Boolean.parseBoolean(webprint);
|
||||
|
||||
Optional<GitRepoModel> grmo = pitchService.cachedRepo(pp);
|
||||
Optional<SlideshowModel> ssmo = pitchService.cachedYAML(pp);
|
||||
|
||||
if (grmo.isPresent() && ssmo.isPresent()) {
|
||||
|
||||
if (isOffline)
|
||||
log.info("slideshow: [ deps, cached, offlne ] {}", pp);
|
||||
else
|
||||
log.info("slideshow: [ deps, cached, online ] {}", pp);
|
||||
|
||||
GitRepoModel grm = grmo.get();
|
||||
GitRepoRenderer rndr =
|
||||
GitRepoRenderer.build(pp, grm, runtime, grsManager.listGRS());
|
||||
SlideshowModel ssm = ssmo.get();
|
||||
/*
|
||||
* Clone cached SlideshowModel in order to adjust for any
|
||||
* changes on the current PitchParams, such as {theme}.
|
||||
*/
|
||||
ssm = ssm.clone(pp);
|
||||
|
||||
return CompletableFuture.completedFuture(
|
||||
ok(com.gitpitch.views.html.Slideshow.render(ssm, rndr, deps,
|
||||
gaToken(), isOffline, serverPrinting, webPrinting)));
|
||||
} else {
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
return pitchService.fetchRepo(pp);
|
||||
|
||||
}, frontEndThreads.POOL)
|
||||
.thenApply(repoFetched -> {
|
||||
|
||||
GitRepoRenderer rndr =
|
||||
GitRepoRenderer.build(pp, repoFetched, runtime,
|
||||
grsManager.listGRS());
|
||||
|
||||
if (ssmo.isPresent()) {
|
||||
|
||||
if (webPrinting)
|
||||
log.info("slideshow: [ repo, fetchd, printg ] {}", pp);
|
||||
else
|
||||
if (isOffline)
|
||||
log.info("slideshow: [ repo, fetchd, offlne ] {}", pp);
|
||||
else
|
||||
log.info("slideshow: [ repo, fetchd, online ] {}", pp);
|
||||
|
||||
SlideshowModel ssm = ssmo.get();
|
||||
/*
|
||||
* Clone cached SlideshowModel in order to adjust for any
|
||||
* changes on the current PitchParams, such as {theme}.
|
||||
*/
|
||||
ssm = ssm.clone(pp);
|
||||
return ok(com.gitpitch.views.html.Slideshow.render(ssm,
|
||||
rndr, deps, gaToken(),
|
||||
isOffline, serverPrinting, webPrinting));
|
||||
|
||||
} else {
|
||||
|
||||
SlideshowModel ssm = pitchService.fetchYAML(pp);
|
||||
|
||||
if (webPrinting)
|
||||
log.info("slideshow: [ yaml, fetchd, printg ] {}", pp);
|
||||
else
|
||||
if (isOffline)
|
||||
log.info("slideshow: [ yaml, fetchd, offlne ] {}", pp);
|
||||
else
|
||||
log.info("slideshow: [ yaml, fetchd, online ] {}", pp);
|
||||
|
||||
return ok(com.gitpitch.views.html.Slideshow.render(ssm,
|
||||
rndr, deps, gaToken(),
|
||||
isOffline, serverPrinting, webPrinting));
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
} // slideshow action
|
||||
|
||||
/*
|
||||
* Markdown processes and renders PITCHME.md markdown.
|
||||
*/
|
||||
public CompletionStage<Result> markdown(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String pitchme) {
|
||||
|
||||
PitchParams pp =
|
||||
PitchParams.build(grsOnCall(grs),
|
||||
user, repo, branch, null, pitchme);
|
||||
Optional<Markdown> mdmo = pitchService.cachedMarkdown(pp);
|
||||
|
||||
if (mdmo.isPresent()) {
|
||||
|
||||
Markdown mdm = mdmo.get();
|
||||
log.info("markdown: [ mdwn, cached, online ] {}", pp);
|
||||
return CompletableFuture.completedFuture(ok(mdm.produce())
|
||||
.as("text/markdown"));
|
||||
|
||||
} else {
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
return pitchService.fetchMarkdown(pp);
|
||||
|
||||
}, frontEndThreads.POOL)
|
||||
.thenApply(fetched -> {
|
||||
|
||||
if (fetched != null) {
|
||||
log.info("markdown: [ mdwn, fetchd, online ] {}", pp);
|
||||
return ok(fetched.produce()).as("text/markdown");
|
||||
}
|
||||
if (pp.isMaster()) {
|
||||
log.info("markdown: [ mdwn, notfnd, online ] {}", pp);
|
||||
return ok(RFE.master(pp, grsManager.get(pp)))
|
||||
.as("text/markdown");
|
||||
} else {
|
||||
log.info("markdown: [ mdwn, notfnd, online ] {}", pp);
|
||||
return ok(RFE.branch(pp, grsManager.get(pp)))
|
||||
.as("text/markdown");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // markdown action
|
||||
|
||||
/*
|
||||
* Home generates presentation home side-panel.
|
||||
*/
|
||||
public CompletionStage<Result> home(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String theme,
|
||||
String pitchme,
|
||||
String offline) {
|
||||
|
||||
PitchParams pp =
|
||||
PitchParams.build(grsOnCall(grs),
|
||||
user, repo, branch, theme, pitchme);
|
||||
|
||||
boolean isOffline =
|
||||
(offline == null) ? false : Boolean.parseBoolean(offline);
|
||||
|
||||
Optional<GitRepoModel> grmo = pitchService.cachedRepo(pp);
|
||||
|
||||
GitRepoModel grm = grmo.orElse(null);
|
||||
GitRepoRenderer rndr =
|
||||
GitRepoRenderer.build(pp, grm, runtime, grsManager.listGRS());
|
||||
|
||||
return CompletableFuture.completedFuture(
|
||||
ok(com.gitpitch.views.html.Home.render(rndr,
|
||||
deps,
|
||||
isOffline,
|
||||
userAgentIsChrome())));
|
||||
} // home action
|
||||
|
||||
/*
|
||||
* Git generates presentation git (grs) side-panel.
|
||||
*/
|
||||
public CompletionStage<Result> git(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String theme,
|
||||
String pitchme,
|
||||
String offline) {
|
||||
|
||||
PitchParams pp =
|
||||
PitchParams.build(grsOnCall(grs),
|
||||
user, repo, branch, theme, pitchme);
|
||||
|
||||
boolean isOffline =
|
||||
(offline == null) ? false : Boolean.parseBoolean(offline);
|
||||
|
||||
Optional<GitRepoModel> grmo = pitchService.cachedRepo(pp);
|
||||
|
||||
GitRepoModel grm = grmo.orElse(null);
|
||||
GitRepoRenderer rndr =
|
||||
GitRepoRenderer.build(pp, grm, runtime, grsManager.listGRS());
|
||||
|
||||
return CompletableFuture.completedFuture(
|
||||
ok(com.gitpitch.views.html.Git.render(rndr, deps, isOffline)));
|
||||
|
||||
} // git action
|
||||
|
||||
/*
|
||||
* Themes generates presentation themes side-panel.
|
||||
*/
|
||||
public CompletionStage<Result> themes(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String theme,
|
||||
String pitchme,
|
||||
String offline) {
|
||||
|
||||
PitchParams pp =
|
||||
PitchParams.build(grsOnCall(grs),
|
||||
user, repo, branch, theme, pitchme);
|
||||
|
||||
boolean isOffline =
|
||||
(offline == null) ? false : Boolean.parseBoolean(offline);
|
||||
|
||||
Optional<GitRepoModel> grmo = pitchService.cachedRepo(pp);
|
||||
Optional<SlideshowModel> ssmo = pitchService.cachedYAML(pp);
|
||||
|
||||
GitRepoModel grm = grmo.orElse(null);
|
||||
GitRepoRenderer rndr =
|
||||
GitRepoRenderer.build(pp, grm, runtime, grsManager.listGRS());
|
||||
String fixedTheme = null;
|
||||
if(ssmo.isPresent()) {
|
||||
fixedTheme = ssmo.get().fixedTheme() ? ssmo.get().fetchTheme() : null;
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(
|
||||
ok(com.gitpitch.views.html.Themes.render(rndr, deps, fixedTheme, isOffline)));
|
||||
|
||||
} // themes action
|
||||
|
||||
/*
|
||||
* Print generates and renders PITCHME.pdf.
|
||||
*/
|
||||
public CompletionStage<Result> print(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String theme,
|
||||
String pitchme,
|
||||
String notes) {
|
||||
|
||||
PitchParams pp =
|
||||
PitchParams.build(grsOnCall(grs),
|
||||
user, repo, branch, theme, pitchme, notes);
|
||||
Optional<File> pdfo = pitchService.cachedPDF(pp);
|
||||
|
||||
if (pdfo.isPresent()) {
|
||||
|
||||
log.info("print: [ cached, printg ] {}", pp);
|
||||
File pdf = pdfo.get();
|
||||
return CompletableFuture.completedFuture(ok(pdf)
|
||||
.as("application/pdf"));
|
||||
|
||||
} else {
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
return pitchService.fetchPDF(pp);
|
||||
|
||||
}, frontEndThreads.POOL)
|
||||
.thenApply(fetched -> {
|
||||
|
||||
if (fetched != null) {
|
||||
log.info("print: [ fetchd, printg ] {}", pp);
|
||||
return ok(fetched).as("application/pdf");
|
||||
} else {
|
||||
log.info("print: [ failed, printg ] {}", pp);
|
||||
return ok(PITCHME_PRINT_ERROR);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // print action
|
||||
|
||||
/*
|
||||
* Offline generates and renders PITCHME.zip.
|
||||
*/
|
||||
public CompletionStage<Result> offline(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String theme,
|
||||
String pitchme,
|
||||
String notes) {
|
||||
|
||||
|
||||
PitchParams pp =
|
||||
PitchParams.build(grsOnCall(grs),
|
||||
user, repo, branch, theme, pitchme, notes);
|
||||
log.debug("offline: pp={}", pp);
|
||||
|
||||
Optional<File> zipo = pitchService.cachedZip(pp);
|
||||
|
||||
if (zipo.isPresent()) {
|
||||
|
||||
log.info("offline: [ cached, downld ] {}", pp);
|
||||
File zip = zipo.get();
|
||||
return CompletableFuture.completedFuture(ok(zip)
|
||||
.as("application/zip"));
|
||||
|
||||
} else {
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
return pitchService.fetchZip(pp);
|
||||
|
||||
}, frontEndThreads.POOL)
|
||||
.thenApply(fetched -> {
|
||||
|
||||
if (fetched != null) {
|
||||
log.info("offline: [ fetchd, downld ] {}", pp);
|
||||
return ok(fetched).as("application/zip");
|
||||
} else {
|
||||
log.info("offline: [ failed, downld ] {}", pp);
|
||||
return ok(PITCHME_OFFLINE_ERROR);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // offline action
|
||||
|
||||
/*
|
||||
* Gist generates and renders GitHub-Gist HTML for
|
||||
* embedding within slideshows.
|
||||
*/
|
||||
public Result gist(String gid) {
|
||||
return ok(com.gitpitch.views.html.Gist.render(gid, deps));
|
||||
} // gist action
|
||||
|
||||
/*
|
||||
* oembed generates an oEmbed provider response.
|
||||
*/
|
||||
public Result oembed(String url,
|
||||
String format,
|
||||
String width,
|
||||
String height,
|
||||
String maxwidth,
|
||||
String maxheight,
|
||||
String referrer) {
|
||||
|
||||
log.info("oembed: [ {}, {}, {} ]", url, format, referrer);
|
||||
|
||||
PitchEmbed pembed = PitchEmbed.build(grsManager,
|
||||
url,
|
||||
width,
|
||||
height,
|
||||
maxwidth,
|
||||
maxheight);
|
||||
Result result = TODO; // Indicates 501 NotImplemented
|
||||
switch(format) {
|
||||
case OEMBED_JSON:
|
||||
result = ok(Json.toJson(pembed));
|
||||
break;
|
||||
case OEMBED_XML:
|
||||
result = ok(com.gitpitch.views.xml.OEmbed.render(pembed));
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
} // oembed action
|
||||
|
||||
public Result template(String template) {
|
||||
String target = (template != null) ? template : TEMPLATE_UNDEF;
|
||||
String targetArchive = TEMPLATE_REPO + target + TEMPLATE_ZIP;
|
||||
log.info("template: downloading {}", target);
|
||||
return redirect(targetArchive);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine GRS on call, explicitly defined or default.
|
||||
*/
|
||||
private String grsOnCall(String grsParam) {
|
||||
return grsManager.getType(grsParam);
|
||||
}
|
||||
|
||||
private boolean userAgentIsChrome() {
|
||||
boolean isChrome = false;
|
||||
try {
|
||||
String[] userAgentHeaders =
|
||||
request().headers().get(Http.HeaderNames.USER_AGENT);
|
||||
if(userAgentHeaders.length > 0) {
|
||||
String userAgent = userAgentHeaders[0];
|
||||
isChrome = userAgent.contains("Chrome/") ||
|
||||
userAgent.contains("Chromium/");
|
||||
}
|
||||
|
||||
} catch(Exception ex) {}
|
||||
return isChrome;
|
||||
}
|
||||
|
||||
private String gaToken() {
|
||||
return runtime.config("gitpitch.google.analytics.token");
|
||||
}
|
||||
|
||||
private static final String PITCHME_PRINT_ERROR =
|
||||
"GitPitch Slideshow print service temporarily unavailable.";
|
||||
private static final String PITCHME_OFFLINE_ERROR =
|
||||
"GitPitch Slideshow offline service temporarily unavailable.";
|
||||
|
||||
private static final String OEMBED_JSON = "json";
|
||||
private static final String OEMBED_XML = "xml";
|
||||
|
||||
private static final String TEMPLATE_REPO =
|
||||
"https://github.com/gitpitch/templates/archive/";
|
||||
private static final String TEMPLATE_ZIP = ".zip";
|
||||
private static final String TEMPLATE_UNDEF = "UNDEFINED";
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.executors;
|
||||
|
||||
import play.inject.ApplicationLifecycle;
|
||||
|
||||
import javax.inject.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/*
|
||||
* Server thread pool for backend async operations.
|
||||
*/
|
||||
@Singleton
|
||||
public final class BackEndThreads extends BaseThreadPool {
|
||||
|
||||
@Inject
|
||||
public BackEndThreads(ApplicationLifecycle lifecycle) {
|
||||
|
||||
super("Back-End-Pool", 50, lifecycle);
|
||||
|
||||
lifecycle.addStopHook(() -> {
|
||||
|
||||
try {
|
||||
POOL.shutdownNow();
|
||||
} catch (SecurityException ex) {
|
||||
}
|
||||
return CompletableFuture.completedFuture(null);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.executors;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
import play.inject.ApplicationLifecycle;
|
||||
|
||||
import javax.inject.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
/*
|
||||
* Server thread pool for async operations.
|
||||
*/
|
||||
public abstract class BaseThreadPool {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
public final ExecutorService POOL;
|
||||
private final String poolName;
|
||||
private final int poolSize;
|
||||
private final ApplicationLifecycle lifecycle;
|
||||
|
||||
protected BaseThreadPool(String poolName,
|
||||
int poolSize,
|
||||
ApplicationLifecycle lifecycle) {
|
||||
|
||||
this.poolName = poolName;
|
||||
this.poolSize = poolSize;
|
||||
this.lifecycle = lifecycle;
|
||||
|
||||
ThreadFactory namedTF =
|
||||
new ThreadFactoryBuilder().setNameFormat(poolName).build();
|
||||
|
||||
POOL = Executors.newFixedThreadPool(poolSize, namedTF);
|
||||
|
||||
lifecycle.addStopHook(() -> {
|
||||
|
||||
try {
|
||||
POOL.shutdownNow();
|
||||
} catch (SecurityException ex) {
|
||||
log.warn("{}: thread pool shutdown ex={}", ex);
|
||||
} finally {
|
||||
log.info("{}: thread pool shutdown.", poolName);
|
||||
}
|
||||
return CompletableFuture.completedFuture(null);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.executors;
|
||||
|
||||
import play.inject.ApplicationLifecycle;
|
||||
|
||||
import javax.inject.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/*
|
||||
* Server thread pool for frontend async operations.
|
||||
*/
|
||||
@Singleton
|
||||
public final class FrontEndThreads extends BaseThreadPool {
|
||||
|
||||
@Inject
|
||||
public FrontEndThreads(ApplicationLifecycle lifecycle) {
|
||||
|
||||
super("Front-End-Pool", 50, lifecycle);
|
||||
|
||||
lifecycle.addStopHook(() -> {
|
||||
|
||||
try {
|
||||
POOL.shutdownNow();
|
||||
} catch (SecurityException ex) {
|
||||
}
|
||||
return CompletableFuture.completedFuture(null);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.factory;
|
||||
|
||||
import com.gitpitch.models.Markdown;
|
||||
import com.gitpitch.utils.MarkdownRenderer;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/*
|
||||
* MarkdownModel factory.
|
||||
*/
|
||||
public interface MarkdownModelFactory {
|
||||
Markdown create(@Nullable MarkdownRenderer mrndr);
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.filters;
|
||||
|
||||
import play.filters.gzip.GzipFilter;
|
||||
import play.filters.headers.SecurityHeadersFilter;
|
||||
import play.filters.hosts.AllowedHostsFilter;
|
||||
import play.http.HttpFilters;
|
||||
import play.mvc.EssentialFilter;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class PitchFilters implements HttpFilters {
|
||||
|
||||
private EssentialFilter[] filters;
|
||||
|
||||
@Inject
|
||||
public PitchFilters(SecurityHeadersFilter secHeadersFilter,
|
||||
AllowedHostsFilter allowedHostsFilter,
|
||||
GzipFilter gzipFilter) {
|
||||
|
||||
filters = new EssentialFilter[]{secHeadersFilter.asJava(),
|
||||
allowedHostsFilter.asJava(),
|
||||
gzipFilter.asJava()};
|
||||
}
|
||||
|
||||
@Override
|
||||
public EssentialFilter[] filters() {
|
||||
return filters;
|
||||
}
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.git;
|
||||
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/*
|
||||
* Git Respository Service model.
|
||||
*/
|
||||
public class GRS {
|
||||
|
||||
private final String name;
|
||||
private final String type;
|
||||
private final String site;
|
||||
private final String apiBase;
|
||||
private final String apiToken;
|
||||
private final String apiTokenHeader;
|
||||
private final String rawBase;
|
||||
private final String gistBase;
|
||||
private final String branchDelim;
|
||||
private final boolean isDefault;
|
||||
|
||||
private GRS(String name,
|
||||
String type,
|
||||
String site,
|
||||
String apiBase,
|
||||
String apiToken,
|
||||
String apiTokenHeader,
|
||||
String rawBase,
|
||||
String gistBase,
|
||||
String branchDelim,
|
||||
boolean isDefault) {
|
||||
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.site = site;
|
||||
this.apiBase = apiBase;
|
||||
this.apiToken = apiToken;
|
||||
this.apiTokenHeader = apiTokenHeader;
|
||||
this.rawBase = rawBase;
|
||||
this.gistBase = gistBase;
|
||||
this.branchDelim = branchDelim;
|
||||
this.isDefault = isDefault;
|
||||
}
|
||||
|
||||
public static GRS build(Map<String,String> grsCfg) {
|
||||
|
||||
String name = grsCfg.get("name");
|
||||
String type = grsCfg.get("type");
|
||||
String site = grsCfg.get("site");
|
||||
String apiBase = grsCfg.get("apibase");
|
||||
String apiToken = grsCfg.get("apitoken");
|
||||
String apiTokenHeader = grsCfg.get("apitokenheader");
|
||||
String rawBase = grsCfg.get("rawbase");
|
||||
String gistBase = grsCfg.get("gistbase");
|
||||
String branchDelim = grsCfg.get("branchdelim");
|
||||
boolean isDefault = Boolean.parseBoolean(grsCfg.get("default"));
|
||||
|
||||
if(name != null && type != null && site != null &&
|
||||
apiBase != null && rawBase != null) {
|
||||
return new GRS(name, type, site, apiBase, apiToken,
|
||||
apiTokenHeader, rawBase, gistBase, branchDelim, isDefault);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() { return name; }
|
||||
public String getType() { return type; }
|
||||
public String getSite() { return site; }
|
||||
public String getApiBase() { return apiBase; }
|
||||
public String getApiToken() { return apiToken; }
|
||||
public String getApiTokenHeader() { return apiTokenHeader; }
|
||||
public String getRawBase() { return rawBase; }
|
||||
public String getGistBase() { return gistBase; }
|
||||
public String compoundBranch(String branch) {
|
||||
if(branch != null && branchDelim != null) {
|
||||
return branch.replaceAll(branchDelim, COMPOUNDED_BRANCH);
|
||||
} else {
|
||||
return branch;
|
||||
}
|
||||
}
|
||||
public boolean isDefault() { return isDefault; }
|
||||
|
||||
public Map<String,String> getHeaders() {
|
||||
Map<String,String> hdrs = new HashMap<String,String>();
|
||||
if(getApiToken() != null && getApiTokenHeader() != null) {
|
||||
hdrs.put(getApiTokenHeader(), getApiToken());
|
||||
}
|
||||
return hdrs;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "GRS[ " + name + " ][ " + type + " ]";
|
||||
}
|
||||
|
||||
private static final String COMPOUNDED_BRANCH = "/";
|
||||
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.git;
|
||||
|
||||
import com.gitpitch.git.vendors.*;
|
||||
import com.gitpitch.services.DiskService;
|
||||
import com.gitpitch.policies.Runtime;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/*
|
||||
* Git Repository Service manager.
|
||||
*/
|
||||
@Singleton
|
||||
public class GRSManager {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final DiskService diskService;
|
||||
private final Runtime runtime;
|
||||
private final GitHub gitHubService;
|
||||
private final GitLab gitLabService;
|
||||
private final BitBucket bitBucketService;
|
||||
private final Gitea giteaService;
|
||||
private final Gogs gogsService;
|
||||
private final GitBucket gitBucketService;
|
||||
private final Map<String,GRS> grsStore = new HashMap<String,GRS>();
|
||||
private GRS grsDefault;
|
||||
|
||||
@Inject
|
||||
public GRSManager(DiskService diskService,
|
||||
GitHub gitHubService,
|
||||
GitLab gitLabService,
|
||||
BitBucket bitBucketService,
|
||||
Gitea giteaService,
|
||||
Gogs gogsService,
|
||||
GitBucket gitBucketService,
|
||||
Runtime runtime) {
|
||||
|
||||
this.diskService = diskService;
|
||||
|
||||
this.gitHubService = gitHubService;
|
||||
this.gitHubService.init(this, diskService);
|
||||
|
||||
this.gitLabService = gitLabService;
|
||||
this.gitLabService.init(this, diskService);
|
||||
|
||||
this.bitBucketService = bitBucketService;
|
||||
this.bitBucketService.init(this, diskService);
|
||||
|
||||
this.giteaService = giteaService;
|
||||
this.giteaService.init(this, diskService);
|
||||
|
||||
this.gogsService = gogsService;
|
||||
this.gogsService.init(this, diskService);
|
||||
|
||||
this.gitBucketService = gitBucketService;
|
||||
this.gitBucketService.init(this, diskService);
|
||||
|
||||
this.runtime = runtime;
|
||||
|
||||
List grsCfg = runtime.configList("gitpitch.git.repo.services");
|
||||
List<HashMap<String,String>> grsCfgList = (List<HashMap<String,String>>) grsCfg;
|
||||
|
||||
GRS fallback = GRS.build(GRS_FALLBACK);
|
||||
|
||||
for(HashMap<String,String> grsMap : grsCfgList) {
|
||||
GRS grs = GRS.build(grsMap);
|
||||
|
||||
if(grs != null) {
|
||||
|
||||
grsStore.put(grs.getType(), grs);
|
||||
if(grs.isDefault())
|
||||
grsDefault = grs;
|
||||
|
||||
} else {
|
||||
log.warn("rejecting: {}", grsMap);
|
||||
}
|
||||
}
|
||||
|
||||
if(grsStore.isEmpty()) {
|
||||
grsStore.put(fallback.getType(), fallback);
|
||||
grsDefault = fallback;
|
||||
log.info("fallback: {}, type={}, true",
|
||||
grsDefault.getName(), grsDefault.getType());
|
||||
}
|
||||
|
||||
if(grsDefault == null) {
|
||||
grsDefault = fallback;
|
||||
}
|
||||
|
||||
grsStore.forEach((k,v) -> {
|
||||
log.info("activating: {}, type={}, default={}",
|
||||
v.getName(), k, v.isDefault());
|
||||
});
|
||||
}
|
||||
|
||||
public GRS get(PitchParams pp) {
|
||||
return get(pp.grs);
|
||||
}
|
||||
|
||||
public GRS get(String grsType) {
|
||||
GRS grs = grsStore.get(grsType);
|
||||
return (grs != null) ? grs : grsDefault;
|
||||
}
|
||||
|
||||
public String getType(String grsType) {
|
||||
GRS grs = grsStore.get(grsType);
|
||||
return (grs != null) ? grs.getType() : grsDefault.getType();
|
||||
}
|
||||
|
||||
public GRSService getService(GRS grs) {
|
||||
|
||||
GRSService service;
|
||||
|
||||
switch(grs.getType()) {
|
||||
|
||||
case GitHub.TYPE:
|
||||
log.debug("getService: matching GitHub");
|
||||
service = gitHubService;
|
||||
break;
|
||||
case GitLab.TYPE:
|
||||
log.debug("getService: matching GitLab");
|
||||
service = gitLabService;
|
||||
break;
|
||||
case BitBucket.TYPE:
|
||||
log.debug("getService: matching BitBucket");
|
||||
service = bitBucketService;
|
||||
break;
|
||||
case Gitea.TYPE:
|
||||
log.debug("getService: matching Gitea");
|
||||
service = giteaService;
|
||||
break;
|
||||
case Gogs.TYPE:
|
||||
log.debug("getService: matching Gogs");
|
||||
service = gogsService;
|
||||
break;
|
||||
case GitBucket.TYPE:
|
||||
log.debug("getService: matching GitBucket");
|
||||
service = gitBucketService;
|
||||
break;
|
||||
default:
|
||||
log.debug("getService: defaulting GitHub");
|
||||
service = gitHubService;
|
||||
}
|
||||
|
||||
log.debug("getService: returning={}", service);
|
||||
return service;
|
||||
}
|
||||
|
||||
public List<GRS> listGRS() {
|
||||
List<GRS> services = grsStore.entrySet()
|
||||
.stream()
|
||||
.map(Map.Entry::getValue)
|
||||
.collect(Collectors.toList());
|
||||
log.debug("listGRS: {}", services);
|
||||
return services;
|
||||
}
|
||||
|
||||
static Map<String,String> GRS_FALLBACK = new HashMap<String, String>();
|
||||
static {
|
||||
GRS_FALLBACK.put("name", "GitHub");
|
||||
GRS_FALLBACK.put("type", "github");
|
||||
GRS_FALLBACK.put("apibase", "https://api.github.com/");
|
||||
GRS_FALLBACK.put("apitoken", null);
|
||||
GRS_FALLBACK.put("rawbase", "https://raw.githubusercontent.com/");
|
||||
GRS_FALLBACK.put("default", "true");
|
||||
}
|
||||
}
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.git;
|
||||
|
||||
import com.gitpitch.git.*;
|
||||
import com.gitpitch.models.GitRepoModel;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.services.DiskService;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* Git Respository Service common interface.
|
||||
*/
|
||||
public abstract class GRSService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
protected final AtomicInteger cacheBypass = new AtomicInteger();
|
||||
protected GRSManager grsManager;
|
||||
protected DiskService diskService;
|
||||
|
||||
public void init(GRSManager grsManager,
|
||||
DiskService diskService) {
|
||||
this.grsManager = grsManager;
|
||||
this.diskService = diskService;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if apiPath is a call on this GRSService instance.
|
||||
*/
|
||||
public boolean call(PitchParams pp, String apiPath) {
|
||||
|
||||
if(apiPath != null) {
|
||||
GRS grs = grsManager.get(pp);
|
||||
return apiPath.startsWith(grs.getApiBase()) ||
|
||||
apiPath.startsWith(grs.getRawBase());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return zero if file download completes successfully.
|
||||
*/
|
||||
public int download(PitchParams pp, String filename, String filePath) {
|
||||
|
||||
int status = 999;
|
||||
|
||||
GRS grs = grsManager.get(pp);
|
||||
GRSService grsService = grsManager.getService(grs);
|
||||
Path branchPath = diskService.ensure(pp);
|
||||
String grsLink = raw(pp, filePath, true);
|
||||
log.debug("download: grsLink={}", grsLink);
|
||||
|
||||
if (grsService.call(pp, grsLink)) {
|
||||
status = diskService.download(pp,
|
||||
branchPath,
|
||||
grsLink,
|
||||
filename,
|
||||
grs.getHeaders());
|
||||
}
|
||||
|
||||
log.debug("download: returning status={}", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return model representing Git repository meta-data.
|
||||
*/
|
||||
public abstract GitRepoModel model(PitchParams pp, JsonNode json);
|
||||
|
||||
/*
|
||||
* Return Raw API path for /user/repo/branch.
|
||||
*/
|
||||
public abstract String raw(PitchParams pp);
|
||||
|
||||
/*
|
||||
* Return Raw API path for /user/repo/branch/filename.
|
||||
*/
|
||||
public String raw(PitchParams pp, String filename) {
|
||||
return raw(pp, filename, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return Raw API path for /user/repo/branch/filename with
|
||||
* optional query param used to bypass GRS API caching.
|
||||
*/
|
||||
public String raw(PitchParams pp,
|
||||
String filename,
|
||||
boolean bypassCache) {
|
||||
|
||||
if (bypassCache) {
|
||||
return raw(pp) + filename +
|
||||
"?gp=" + cacheBypass.getAndIncrement();
|
||||
} else {
|
||||
return raw(pp) + filename;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return API path for repository meta call for /user/repo.
|
||||
*/
|
||||
public abstract String repo(PitchParams pp);
|
||||
|
||||
/*
|
||||
* Return GIST API path for code snippet identified by gid.
|
||||
*/
|
||||
public String gist(PitchParams pp, String gid) {
|
||||
return gist(pp, gid, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return GIST API path for code snippet identified by
|
||||
* file (fid) on code snippet (gid).
|
||||
*/
|
||||
public abstract String gist(PitchParams pp, String gid, String fid);
|
||||
|
||||
protected static final String SLASH = "/";
|
||||
protected static final String NOT_FOUND = "#";
|
||||
|
||||
}
|
82
app/com/gitpitch/git/vendors/BitBucket.java
vendored
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.git.vendors;
|
||||
|
||||
import com.gitpitch.git.*;
|
||||
import com.gitpitch.models.*;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.services.DiskService;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* BitBucket API Service.
|
||||
*/
|
||||
@Singleton
|
||||
public class BitBucket extends GRSService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
public GitRepoModel model(PitchParams pp, JsonNode json) {
|
||||
return BitBucketRepoModel.build(pp, json);
|
||||
}
|
||||
|
||||
public String raw(PitchParams pp) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
return new StringBuffer(grs.getRawBase())
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.append(BITBUCKET_RAW)
|
||||
.append(grs.compoundBranch(pp.branch))
|
||||
.append(SLASH)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String repo(PitchParams pp) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
return new StringBuffer(grs.getApiBase())
|
||||
.append(BITBUCKET_REPO_API)
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String gist(PitchParams pp, String gid, String fid) {
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
public static final String TYPE = "bitbucket";
|
||||
private static final String BITBUCKET_REPO_API = "repositories/";
|
||||
private static final String BITBUCKET_RAW = "/raw/";
|
||||
}
|
82
app/com/gitpitch/git/vendors/GitBucket.java
vendored
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.git.vendors;
|
||||
|
||||
import com.gitpitch.git.*;
|
||||
import com.gitpitch.models.*;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/*
|
||||
* GitBucket API Service.
|
||||
*/
|
||||
@Singleton
|
||||
public class GitBucket extends GRSService {
|
||||
|
||||
private final ALogger log = Logger.of(this.getClass());
|
||||
|
||||
public GitRepoModel model(PitchParams pp, JsonNode json) {
|
||||
return GitHubRepoModel.build(pp, json);
|
||||
}
|
||||
|
||||
public String raw(PitchParams pp) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
return new StringBuffer(grs.getApiBase())
|
||||
.append(GITBUCKET_REPO_API)
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.append(SLASH)
|
||||
.append(GITBUCKET_RAW_API)
|
||||
.append(grs.compoundBranch(pp.branch))
|
||||
.append(SLASH)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String repo(PitchParams pp) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
return new StringBuffer(grs.getApiBase())
|
||||
.append(GITBUCKET_REPO_API)
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String gist(PitchParams pp, String gid, String fid) {
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
public static final String TYPE = "gitbucket";
|
||||
private static final String GITBUCKET_REPO_API = "repos/";
|
||||
private static final String GITBUCKET_RAW_API = "raw/";
|
||||
}
|
94
app/com/gitpitch/git/vendors/GitHub.java
vendored
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.git.vendors;
|
||||
|
||||
import com.gitpitch.git.*;
|
||||
import com.gitpitch.models.*;
|
||||
import com.gitpitch.services.DiskService;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* GitHub API Service.
|
||||
*/
|
||||
@Singleton
|
||||
public class GitHub extends GRSService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
public GitRepoModel model(PitchParams pp, JsonNode json) {
|
||||
return GitHubRepoModel.build(pp, json);
|
||||
}
|
||||
|
||||
public String raw(PitchParams pp) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
return new StringBuffer(grs.getRawBase())
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.append(SLASH)
|
||||
.append(grs.compoundBranch(pp.branch))
|
||||
.append(SLASH)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String repo(PitchParams pp) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
return new StringBuffer(grs.getApiBase())
|
||||
.append(GITHUB_REPO_API)
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String gist(PitchParams pp, String gid, String fid) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
StringBuffer gistLink = new StringBuffer(grs.getGistBase())
|
||||
.append(gid)
|
||||
.append(SLASH)
|
||||
.append(GITHUB_GIST_RAW);
|
||||
|
||||
if(fid != null) {
|
||||
gistLink = gistLink.append(SLASH).append(fid);
|
||||
}
|
||||
|
||||
return gistLink.toString();
|
||||
}
|
||||
|
||||
public static final String TYPE = "github";
|
||||
private static final String GITHUB_REPO_API = "repos/";
|
||||
private static final String GITHUB_GIST_RAW = "raw";
|
||||
}
|
92
app/com/gitpitch/git/vendors/GitLab.java
vendored
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.git.vendors;
|
||||
|
||||
import com.gitpitch.git.*;
|
||||
import com.gitpitch.models.*;
|
||||
import com.gitpitch.services.DiskService;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* GitLab API Service.
|
||||
*/
|
||||
@Singleton
|
||||
public class GitLab extends GRSService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
public GitRepoModel model(PitchParams pp, JsonNode json) {
|
||||
return GitLabRepoModel.build(pp, json);
|
||||
}
|
||||
|
||||
public String raw(PitchParams pp) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
return new StringBuffer(grs.getRawBase())
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.append(GITLAB_RAW)
|
||||
.append(grs.compoundBranch(pp.branch))
|
||||
.append(SLASH)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String repo(PitchParams pp) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
return new StringBuffer(grs.getApiBase())
|
||||
.append(GITLAB_PROJECTS_API)
|
||||
.append(genProjectId(pp))
|
||||
.toString();
|
||||
}
|
||||
|
||||
private String genProjectId(PitchParams pp) {
|
||||
|
||||
String userRepo =
|
||||
new StringBuffer(pp.user).append(SLASH)
|
||||
.append(pp.repo)
|
||||
.toString();
|
||||
|
||||
String pid = java.net.URLEncoder.encode(userRepo);
|
||||
log.debug("genProjectId: pid={}", pid);
|
||||
return pid;
|
||||
}
|
||||
|
||||
public String gist(PitchParams pp, String gid, String fid) {
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
public static final String TYPE = "gitlab";
|
||||
private static final String GITLAB_PROJECTS_API = "projects/";
|
||||
private static final String GITLAB_RAW = "/raw/";
|
||||
}
|
82
app/com/gitpitch/git/vendors/Gitea.java
vendored
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.git.vendors;
|
||||
|
||||
import com.gitpitch.git.*;
|
||||
import com.gitpitch.models.*;
|
||||
import com.gitpitch.services.DiskService;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* Gitea API Service.
|
||||
*/
|
||||
@Singleton
|
||||
public class Gitea extends GRSService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
public GitRepoModel model(PitchParams pp, JsonNode json) {
|
||||
return GiteaRepoModel.build(pp, json);
|
||||
}
|
||||
|
||||
public String raw(PitchParams pp) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
return new StringBuffer(grs.getRawBase())
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.append(GITEA_RAW)
|
||||
.append(grs.compoundBranch(pp.branch))
|
||||
.append(SLASH)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String repo(PitchParams pp) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
return new StringBuffer(grs.getApiBase())
|
||||
.append(GITEA_REPO_API)
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String gist(PitchParams pp, String gid, String fid) {
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
public static final String TYPE = "gitea";
|
||||
private static final String GITEA_REPO_API = "repos/";
|
||||
private static final String GITEA_RAW = "/raw/branch/";
|
||||
}
|
82
app/com/gitpitch/git/vendors/Gogs.java
vendored
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.git.vendors;
|
||||
|
||||
import com.gitpitch.git.*;
|
||||
import com.gitpitch.models.*;
|
||||
import com.gitpitch.services.DiskService;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* Gogs API Service.
|
||||
*/
|
||||
@Singleton
|
||||
public class Gogs extends GRSService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
public GitRepoModel model(PitchParams pp, JsonNode json) {
|
||||
return GogsRepoModel.build(pp, json);
|
||||
}
|
||||
|
||||
public String raw(PitchParams pp) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
return new StringBuffer(grs.getRawBase())
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.append(GOGS_RAW)
|
||||
.append(grs.compoundBranch(pp.branch))
|
||||
.append(SLASH)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String repo(PitchParams pp) {
|
||||
|
||||
GRS grs = grsManager.get(TYPE);
|
||||
|
||||
return new StringBuffer(grs.getApiBase())
|
||||
.append(GOGS_REPO_API)
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String gist(PitchParams pp, String gid, String fid) {
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
public static final String TYPE = "gogs";
|
||||
private static final String GOGS_REPO_API = "repos/";
|
||||
private static final String GOGS_RAW = "/raw/";
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.models;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* Rendering model for views.Slideshow.scala.html.
|
||||
*/
|
||||
public class BitBucketRepoModel extends GitRepoModel {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
/*
|
||||
* Initialize instance of BitBucketRepoModel.
|
||||
*/
|
||||
private BitBucketRepoModel(PitchParams pp) {
|
||||
this(pp, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize instance of BitBucketRepoModel.
|
||||
*/
|
||||
private BitBucketRepoModel(PitchParams pp,
|
||||
JsonNode json) {
|
||||
|
||||
this._pp = pp;
|
||||
|
||||
if(pp != null) {
|
||||
this._pretty = new StringBuffer(SLASH)
|
||||
.append(this._pp.user)
|
||||
.append(SLASH)
|
||||
.append(this._pp.repo)
|
||||
.toString();
|
||||
this._cacheKey = genKey(pp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate derived data on instance only if the BitBucket
|
||||
* API JSON is available for processing.
|
||||
*/
|
||||
if (json != null) {
|
||||
JsonNode ownerNode = json.findPath(OWNER);
|
||||
this._type = ownerNode.findPath(TYPE).textValue();
|
||||
this._desc = json.findPath(DESCRIPTION).textValue();
|
||||
this._created = json.findPath(CREATED_ON).textValue();
|
||||
this._updated = json.findPath(UPDATED_ON).textValue();
|
||||
this._lang = json.findPath(LANGUAGE).textValue();
|
||||
this._stars = 0;
|
||||
this._forks = 0;
|
||||
this._issues = 0;
|
||||
this._hasWiki = json.findPath(HAS_WIKI).asBoolean();
|
||||
this._hasPages = false;
|
||||
this._private = json.findPath(IS_PRIVATE).asBoolean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static GitRepoModel build(PitchParams pp) {
|
||||
return build(pp, null);
|
||||
}
|
||||
|
||||
public static GitRepoModel build(PitchParams pp, JsonNode json) {
|
||||
return new BitBucketRepoModel(pp, json);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.models;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* Rendering model for views.Slideshow.scala.html.
|
||||
*/
|
||||
public class GitHubRepoModel extends GitRepoModel {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
/*
|
||||
* Initialize instance of GitHubRepoModel.
|
||||
*/
|
||||
private GitHubRepoModel(PitchParams pp) {
|
||||
this(pp, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize instance of GitHubRepoModel.
|
||||
*/
|
||||
private GitHubRepoModel(PitchParams pp,
|
||||
JsonNode json) {
|
||||
|
||||
this._pp = pp;
|
||||
|
||||
if(pp != null) {
|
||||
this._pretty = new StringBuffer(SLASH)
|
||||
.append(this._pp.user)
|
||||
.append(SLASH)
|
||||
.append(this._pp.repo)
|
||||
.toString();
|
||||
this._cacheKey = genKey(pp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate derived data on instance only if the GitHub
|
||||
* API JSON is available for processing.
|
||||
*/
|
||||
if (json != null) {
|
||||
JsonNode ownerNode = json.findPath(OWNER);
|
||||
this._type = ownerNode.findPath(TYPE).textValue();
|
||||
this._desc = json.findPath(DESCRIPTION).textValue();
|
||||
this._created = json.findPath(CREATED_AT).textValue();
|
||||
this._updated = json.findPath(UPDATED_AT).textValue();
|
||||
this._lang = json.findPath(LANGUAGE).textValue();
|
||||
this._stars = json.findPath(STARGAZERS_COUNT).asInt();
|
||||
this._forks = json.findPath(FORKS_COUNT).asInt();
|
||||
this._issues = json.findPath(OPEN_ISSUES).asInt();
|
||||
this._hasWiki = json.findPath(HAS_WIKI).asBoolean();
|
||||
this._hasPages = json.findPath(HAS_PAGES).asBoolean();
|
||||
this._private = json.findPath(PRIVATE).asBoolean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static GitRepoModel build(PitchParams pp) {
|
||||
return build(pp, null);
|
||||
}
|
||||
|
||||
public static GitRepoModel build(PitchParams pp, JsonNode json) {
|
||||
return new GitHubRepoModel(pp, json);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.models;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* Rendering model for views.Slideshow.scala.html.
|
||||
*/
|
||||
public class GitLabRepoModel extends GitRepoModel {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
/*
|
||||
* Initialize instance of GitLabRepoModel.
|
||||
*/
|
||||
private GitLabRepoModel(PitchParams pp) {
|
||||
this(pp, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize instance of GitLabRepoModel.
|
||||
*/
|
||||
private GitLabRepoModel(PitchParams pp,
|
||||
JsonNode json) {
|
||||
|
||||
this._pp = pp;
|
||||
|
||||
if(pp != null) {
|
||||
this._pretty = new StringBuffer(SLASH)
|
||||
.append(this._pp.user)
|
||||
.append(SLASH)
|
||||
.append(this._pp.repo)
|
||||
.toString();
|
||||
this._cacheKey = genKey(pp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate derived data on instance only if the GitLab
|
||||
* API JSON is available for processing.
|
||||
*/
|
||||
if (json != null) {
|
||||
this._type = USER_TYPE;
|
||||
this._desc = json.findPath(DESCRIPTION).textValue();
|
||||
this._lang = null;
|
||||
JsonNode namespaceNode = json.findPath(NAMESPACE);
|
||||
if(namespaceNode != null) {
|
||||
this._created = namespaceNode.findPath(CREATED_AT).textValue();
|
||||
this._updated = namespaceNode.findPath(UPDATED_AT).textValue();
|
||||
}
|
||||
this._stars = json.findPath(STAR_COUNT).asInt();
|
||||
this._forks = json.findPath(FORKS_COUNT).asInt();
|
||||
this._issues = json.findPath(OPEN_ISSUES_COUNT).asInt();
|
||||
this._hasWiki = json.findPath(WIKI_ENABLED).asBoolean();
|
||||
this._hasPages = false;
|
||||
this._private = json.findPath(VISIBILITY).textValue() != PUBLIC;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static GitRepoModel build(PitchParams pp) {
|
||||
return build(pp, null);
|
||||
}
|
||||
|
||||
public static GitRepoModel build(PitchParams pp, JsonNode json) {
|
||||
return new GitLabRepoModel(pp, json);
|
||||
}
|
||||
|
||||
private static final String USER_TYPE = "User";
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.models;
|
||||
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* Rendering model for views.Slideshow.scala.html.
|
||||
*/
|
||||
public abstract class GitRepoModel {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
/*
|
||||
* PitchParams.
|
||||
*/
|
||||
protected PitchParams _pp;
|
||||
/*
|
||||
* Git repository owner type: User or Organization.
|
||||
*/
|
||||
protected String _type;
|
||||
/*
|
||||
* Git repository description.
|
||||
*/
|
||||
protected String _desc;
|
||||
/*
|
||||
* Git repository creation date.
|
||||
*/
|
||||
protected String _created;
|
||||
/*
|
||||
* Git repository last updated date.
|
||||
*/
|
||||
protected String _updated;
|
||||
/*
|
||||
* Git repository language.
|
||||
*/
|
||||
protected String _lang;
|
||||
/*
|
||||
* Git repository stargazers_count.
|
||||
*/
|
||||
protected int _stars;
|
||||
/*
|
||||
* Git repository forks_count.
|
||||
*/
|
||||
protected int _forks;
|
||||
/*
|
||||
* Git repository open issues count.
|
||||
*/
|
||||
protected int _issues;
|
||||
/*
|
||||
* Git repository has Wiki flag.
|
||||
*/
|
||||
protected boolean _hasWiki;
|
||||
/*
|
||||
* Git repository has Pages (website) flag.
|
||||
*/
|
||||
protected boolean _hasPages;
|
||||
/*
|
||||
* Derived immutable state.
|
||||
*/
|
||||
protected String _pretty;
|
||||
protected String _cacheKey;
|
||||
/*
|
||||
* Git repo visibility.
|
||||
*/
|
||||
protected boolean _private;
|
||||
|
||||
/*
|
||||
* Generate a key for querying the cache for matching GitRepoModel.
|
||||
*/
|
||||
public static String genKey(PitchParams pp) {
|
||||
|
||||
return new StringBuffer(MODEL_ID).append(SLASH)
|
||||
.append(pp.grs)
|
||||
.append(SLASH)
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String owner() {
|
||||
return _pp.user;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return _pp.repo;
|
||||
}
|
||||
|
||||
public String description() {
|
||||
return _desc;
|
||||
}
|
||||
|
||||
public String lang() {
|
||||
return _lang;
|
||||
}
|
||||
|
||||
public boolean byOrg() {
|
||||
return GIT_TYPE_ORG.equals(_type);
|
||||
}
|
||||
|
||||
public int stargazers() {
|
||||
return _stars;
|
||||
}
|
||||
|
||||
public int forks() {
|
||||
return _forks;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return _pretty;
|
||||
}
|
||||
|
||||
public String key() {
|
||||
return _cacheKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* Repo API JSON response property names.
|
||||
*/
|
||||
protected static final String OWNER = "owner";
|
||||
protected static final String TYPE = "type";
|
||||
protected static final String DESCRIPTION = "description";
|
||||
protected static final String CREATED_AT = "created_at";
|
||||
protected static final String UPDATED_AT = "updated_at";
|
||||
protected static final String CREATED_ON = "created_on";
|
||||
protected static final String UPDATED_ON = "updated_on";
|
||||
protected static final String LANGUAGE = "language";
|
||||
protected static final String STARGAZERS_COUNT = "stargazers_count";
|
||||
protected static final String STAR_COUNT = "star_count";
|
||||
protected static final String FORKS_COUNT = "forks_count";
|
||||
protected static final String OPEN_ISSUES = "open_issues";
|
||||
protected static final String OPEN_ISSUES_COUNT = "open_issues_count";
|
||||
protected static final String HAS_WIKI = "has_wiki";
|
||||
protected static final String WIKI_ENABLED = "wiki_enabled";
|
||||
protected static final String HAS_PAGES = "has_pages";
|
||||
protected static final String PUBLIC = "public";
|
||||
protected static final String PRIVATE = "private";
|
||||
protected static final String IS_PRIVATE = "is_private";
|
||||
protected static final String NAMESPACE = "namespace";
|
||||
protected static final String VISIBILITY = "visiblity";
|
||||
|
||||
protected static final String GIT_TYPE_ORG = "Organization";
|
||||
protected static final String SLASH = "/";
|
||||
/*
|
||||
* Model prefix identifier for cache key generator.
|
||||
*/
|
||||
private static final String MODEL_ID = "GRM:";
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.models;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* Rendering model for views.Slideshow.scala.html.
|
||||
*/
|
||||
public class GiteaRepoModel extends GitRepoModel {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
/*
|
||||
* Initialize instance of GiteaRepoModel.
|
||||
*/
|
||||
private GiteaRepoModel(PitchParams pp) {
|
||||
this(pp, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize instance of GiteaRepoModel.
|
||||
*/
|
||||
private GiteaRepoModel(PitchParams pp, JsonNode json) {
|
||||
|
||||
this._pp = pp;
|
||||
|
||||
this._pretty = new StringBuffer(SLASH)
|
||||
.append(this._pp.user)
|
||||
.append(SLASH)
|
||||
.append(this._pp.repo)
|
||||
.toString();
|
||||
|
||||
this._cacheKey = genKey(pp);
|
||||
|
||||
/*
|
||||
* Generate derived data on instance only if the GitHub
|
||||
* API JSON is available for processing.
|
||||
*/
|
||||
if (json != null) {
|
||||
|
||||
JsonNode ownerNode = json.findPath("owner");
|
||||
this._type = null;
|
||||
|
||||
this._desc = json.findPath("description").textValue();
|
||||
this._created = json.findPath("created_at").textValue();
|
||||
this._updated = json.findPath("updated_at").textValue();
|
||||
this._lang = null;
|
||||
|
||||
this._stars = json.findPath("stars_count").asInt();
|
||||
this._forks = json.findPath("forks_count").asInt();
|
||||
this._issues = json.findPath("open_issues.count").asInt();
|
||||
|
||||
this._hasWiki = false;
|
||||
this._hasPages = false;
|
||||
|
||||
} else {
|
||||
|
||||
this._type = null;
|
||||
|
||||
this._desc = null;
|
||||
this._created = null;
|
||||
this._updated = null;
|
||||
this._lang = null;
|
||||
|
||||
this._stars = 0;
|
||||
this._forks = 0;
|
||||
this._issues = 0;
|
||||
|
||||
this._hasWiki = false;
|
||||
this._hasPages = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static GitRepoModel build(PitchParams pp) {
|
||||
return build(pp, null);
|
||||
}
|
||||
|
||||
public static GitRepoModel build(PitchParams pp, JsonNode json) {
|
||||
return new GiteaRepoModel(pp, json);
|
||||
}
|
||||
|
||||
public String owner() {
|
||||
return _pp.user;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return _pp.repo;
|
||||
}
|
||||
|
||||
public String description() {
|
||||
return _desc;
|
||||
}
|
||||
|
||||
public String lang() {
|
||||
return _lang;
|
||||
}
|
||||
|
||||
public boolean byOrg() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int stargazers() {
|
||||
return _stars;
|
||||
}
|
||||
|
||||
public int forks() {
|
||||
return _forks;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return _pretty;
|
||||
}
|
||||
|
||||
public String key() {
|
||||
return _cacheKey;
|
||||
}
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.models;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* Rendering model for views.Slideshow.scala.html.
|
||||
*/
|
||||
public class GogsRepoModel extends GitRepoModel {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
/*
|
||||
* Initialize instance of GogsRepoModel.
|
||||
*/
|
||||
private GogsRepoModel(PitchParams pp) {
|
||||
this(pp, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize instance of GogsRepoModel.
|
||||
*/
|
||||
private GogsRepoModel(PitchParams pp, JsonNode json) {
|
||||
|
||||
this._pp = pp;
|
||||
|
||||
this._pretty = new StringBuffer(SLASH)
|
||||
.append(this._pp.user)
|
||||
.append(SLASH)
|
||||
.append(this._pp.repo)
|
||||
.toString();
|
||||
|
||||
this._cacheKey = genKey(pp);
|
||||
|
||||
/*
|
||||
* Generate derived data on instance only if the GitHub
|
||||
* API JSON is available for processing.
|
||||
*/
|
||||
if (json != null) {
|
||||
|
||||
JsonNode ownerNode = json.findPath("owner");
|
||||
this._type = null;
|
||||
|
||||
this._desc = json.findPath("description").textValue();
|
||||
this._created = json.findPath("created_at").textValue();
|
||||
this._updated = json.findPath("updated_at").textValue();
|
||||
this._lang = null;
|
||||
|
||||
this._stars = json.findPath("stars_count").asInt();
|
||||
this._forks = json.findPath("forks_count").asInt();
|
||||
this._issues = json.findPath("open_issues.count").asInt();
|
||||
|
||||
this._hasWiki = false;
|
||||
this._hasPages = false;
|
||||
|
||||
} else {
|
||||
|
||||
this._type = null;
|
||||
|
||||
this._desc = null;
|
||||
this._created = null;
|
||||
this._updated = null;
|
||||
this._lang = null;
|
||||
|
||||
this._stars = 0;
|
||||
this._forks = 0;
|
||||
this._issues = 0;
|
||||
|
||||
this._hasWiki = false;
|
||||
this._hasPages = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static GitRepoModel build(PitchParams pp) {
|
||||
return build(pp, null);
|
||||
}
|
||||
|
||||
public static GitRepoModel build(PitchParams pp, JsonNode json) {
|
||||
return new GogsRepoModel(pp, json);
|
||||
}
|
||||
|
||||
public String owner() {
|
||||
return _pp.user;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return _pp.repo;
|
||||
}
|
||||
|
||||
public String description() {
|
||||
return _desc;
|
||||
}
|
||||
|
||||
public String lang() {
|
||||
return _lang;
|
||||
}
|
||||
|
||||
public boolean byOrg() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int stargazers() {
|
||||
return _stars;
|
||||
}
|
||||
|
||||
public int forks() {
|
||||
return _forks;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return _pretty;
|
||||
}
|
||||
|
||||
public String key() {
|
||||
return _cacheKey;
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.models;
|
||||
|
||||
/*
|
||||
* Markdown model interface.
|
||||
*/
|
||||
public interface Markdown {
|
||||
public String produce();
|
||||
public String offline(String md);
|
||||
public String offlineAssets(String md);
|
||||
}
|
|
@ -1,745 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.models;
|
||||
|
||||
import com.gitpitch.models.SlideshowModel;
|
||||
import com.gitpitch.utils.*;
|
||||
import com.gitpitch.services.ImageService;
|
||||
import com.gitpitch.services.VideoService;
|
||||
import com.gitpitch.services.GISTService;
|
||||
import com.gitpitch.services.CodeService;
|
||||
import com.gitpitch.services.ShortcutsService;
|
||||
import com.gitpitch.services.SlideService;
|
||||
import com.gitpitch.git.GRSManager;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import javax.annotation.Nullable;
|
||||
import play.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
/*
|
||||
* Rendering model for PITCHME.md markdown.
|
||||
*/
|
||||
public class MarkdownModel implements Markdown {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final ImageService imageService;
|
||||
private final VideoService videoService;
|
||||
private final GISTService gistService;
|
||||
private final CodeService codeService;
|
||||
private final ShortcutsService shortcutsService;
|
||||
private final SlideService slideService;
|
||||
private final GRSManager grsManager;
|
||||
private final MarkdownRenderer mrndr;
|
||||
private final String markdown;
|
||||
private String hSlideDelim = HSLIDE_DELIM_DEFAULT;
|
||||
private String vSlideDelim = VSLIDE_DELIM_DEFAULT;
|
||||
|
||||
@Inject
|
||||
public MarkdownModel(ImageService imageService,
|
||||
VideoService videoService,
|
||||
GISTService gistService,
|
||||
CodeService codeService,
|
||||
ShortcutsService shortcutsService,
|
||||
SlideService slideService,
|
||||
GRSManager grsManager,
|
||||
@Nullable @Assisted MarkdownRenderer mrndr) {
|
||||
|
||||
this.imageService = imageService;
|
||||
this.videoService = videoService;
|
||||
this.gistService = gistService;
|
||||
this.codeService = codeService;
|
||||
this.shortcutsService = shortcutsService;
|
||||
this.slideService = slideService;
|
||||
this.grsManager = grsManager;
|
||||
this.mrndr = mrndr;
|
||||
|
||||
String consumed = null;
|
||||
|
||||
if(mrndr != null) {
|
||||
|
||||
String gitRawBase = mrndr.gitRawBase();
|
||||
Path mdPath = mrndr.filePath(PITCHME_MD);
|
||||
|
||||
File mdFile = mdPath.toFile();
|
||||
|
||||
if (mdFile.exists()) {
|
||||
|
||||
Optional<SlideshowModel> ssmo = mrndr.ssm();
|
||||
|
||||
final PitchParams pp =
|
||||
ssmo.isPresent() ? ssmo.get().params() : null;
|
||||
final YAMLOptions yOpts =
|
||||
ssmo.isPresent() ? ssmo.get().options() : null;
|
||||
|
||||
if(yOpts != null) {
|
||||
hSlideDelim = yOpts.hasHorzDelim(pp) ?
|
||||
yOpts.fetchHorzDelim(pp) : HSLIDE_DELIM_DEFAULT;
|
||||
vSlideDelim = yOpts.hasVertDelim(pp) ?
|
||||
yOpts.fetchVertDelim(pp) : VSLIDE_DELIM_DEFAULT;
|
||||
}
|
||||
|
||||
try (Stream<String> stream = Files.lines(mdPath)) {
|
||||
|
||||
consumed = stream.map(md -> {
|
||||
return process(md, pp, yOpts, gitRawBase);
|
||||
}).map(md -> {
|
||||
return shortcutsService.process(md, pp, yOpts);
|
||||
}).collect(Collectors.joining("\n"));
|
||||
|
||||
consumed = postProcess(consumed, pp, yOpts, gitRawBase);
|
||||
|
||||
} catch (Exception mex) {
|
||||
log.warn("Markdown processing ex={}", mex);
|
||||
consumed = "PITCHME.md could not be parsed.";
|
||||
}
|
||||
|
||||
} else {
|
||||
log.warn("Markdown file does not exist, {}", mdFile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.markdown = consumed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process text, image, video, gist, and code content
|
||||
* in PITCHME.md for online viewing.
|
||||
*/
|
||||
private String process(String md,
|
||||
PitchParams pp,
|
||||
YAMLOptions yOpts,
|
||||
String gitRawBase) {
|
||||
|
||||
md = processBackwardCompatDelim(md);
|
||||
|
||||
if (slideDelimFound(md)) {
|
||||
|
||||
/*
|
||||
* Clean only delimiter fragments of whitespace
|
||||
* noise before processing. Preserve end-of-line
|
||||
* characters on all non-delimiter fragments.
|
||||
*/
|
||||
md = md.trim();
|
||||
DelimParams dp = DelimParams.build(md);
|
||||
|
||||
if (videoDelimFound(dp)) {
|
||||
|
||||
/*
|
||||
* Inject slide specific video background:
|
||||
*
|
||||
* <!-- .slide: data-background-video="vidUrl" -->
|
||||
*/
|
||||
|
||||
return new StringBuffer(delimiter(md))
|
||||
.append(videoService.buildBackground(md,
|
||||
dp, pp, this))
|
||||
.toString();
|
||||
|
||||
} else if (imageDelimFound(dp)) {
|
||||
|
||||
/*
|
||||
* Inject slide specific image background:
|
||||
*
|
||||
* <!-- .slide: data-background-image="imgUrl" -->
|
||||
*/
|
||||
|
||||
String defaultBgSize = (yOpts != null) ?
|
||||
yOpts.fetchImageBgSize(pp) : YAMLOptions.DEFAULT_BG_SIZE;
|
||||
String defaultBgColor = (yOpts != null) ?
|
||||
yOpts.fetchImageBgColor(pp) : YAMLOptions.DEFAULT_BG_COLOR;
|
||||
String defaultBgPosition = (yOpts != null) ?
|
||||
yOpts.fetchImageBgPosition(pp) : YAMLOptions.DEFAULT_BG_POSITION;
|
||||
String defaultBgRepeat = (yOpts != null) ?
|
||||
yOpts.fetchImageBgRepeat(pp) : YAMLOptions.DEFAULT_BG_REPEAT;
|
||||
String defaultBgTransition = (yOpts != null) ?
|
||||
yOpts.fetchTransition(pp) : YAMLOptions.DEFAULT_TRANSITION;
|
||||
|
||||
return new StringBuffer(delimiter(md))
|
||||
.append(imageService.buildBackground(md,
|
||||
dp,
|
||||
pp,
|
||||
defaultBgSize,
|
||||
defaultBgColor,
|
||||
defaultBgPosition,
|
||||
defaultBgRepeat,
|
||||
defaultBgTransition,
|
||||
this)).toString();
|
||||
|
||||
} else if (gistDelimFound(dp)) {
|
||||
return gistService.build(md, dp, pp, yOpts, this);
|
||||
} else if(codeDelimFound(dp)) {
|
||||
return codeService.build(md, dp, pp, yOpts, this);
|
||||
} else if(colorDelimFound(dp)) {
|
||||
return slideService.buildColorBackground(md, dp, pp, yOpts, this);
|
||||
}
|
||||
|
||||
if (yOpts != null && yOpts.hasImageBg()) {
|
||||
|
||||
/*
|
||||
* Inject slideshow-wide background:
|
||||
*
|
||||
* <!-- .slide: data-background-image="imgUrl" -->
|
||||
*/
|
||||
return new StringBuffer(md)
|
||||
.append(imageService.buildBackground(pp, yOpts))
|
||||
.toString();
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* No customization on slide delimiter or background,
|
||||
* return unmodified.
|
||||
*/
|
||||
return md;
|
||||
}
|
||||
|
||||
} else if (markdownLinkFound(md)) {
|
||||
|
||||
/*
|
||||
* Link found in markdown fragment, process.
|
||||
*/
|
||||
|
||||
int delim = md.indexOf(MD_LINK_DELIM);
|
||||
|
||||
if (delim == NOT_FOUND) {
|
||||
|
||||
/*
|
||||
* Valid link syntax not found, return unmodified.
|
||||
*/
|
||||
return md;
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Valid link syntax found, now process link to
|
||||
* handle absolute, (GitHub) relative and video links.
|
||||
*/
|
||||
|
||||
String splitLeft = md.substring(0, delim + 2);
|
||||
String splitRight = md.substring(delim + 2);
|
||||
|
||||
/*
|
||||
* Clone and clean splitRight string to begin
|
||||
* extraction of the pitchLink.
|
||||
*/
|
||||
String pitchLink = cloneLink(splitRight);
|
||||
pitchLink = extractLink(pitchLink, gitRawBase);
|
||||
|
||||
if (videoService.isVideo(pitchLink)) {
|
||||
return videoService.buildVideo(pitchLink);
|
||||
} else if (linkAbsolute(splitRight)) {
|
||||
return md;
|
||||
} else {
|
||||
return splitLeft + gitRawBase + splitRight;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if(imageService.tagFound(md)) {
|
||||
|
||||
String tagLink = imageService.tagLink(md);
|
||||
if (linkAbsolute(tagLink)) {
|
||||
return md;
|
||||
} else {
|
||||
String absTagLink = gitRawBase + tagLink;
|
||||
return md.replace(tagLink, absTagLink);
|
||||
}
|
||||
} else if(shortcutsService.titleHintFound(md)) {
|
||||
return shortcutsService.expandTitleHint(md);
|
||||
} else if(shortcutsService.listFragmentFound(md)) {
|
||||
return shortcutsService.expandListFragment(md);
|
||||
} else if(shortcutsService.codeFragmentFound(md)) {
|
||||
return shortcutsService.expandCodeFragment(md);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Link-free markdown, return unmodified.
|
||||
*/
|
||||
return md;
|
||||
}
|
||||
}
|
||||
|
||||
public String produce() {
|
||||
return markdown;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process text, image, video, gist, and code content
|
||||
* in PITCHME.md for offline viewing.
|
||||
*/
|
||||
public String offline(String md) {
|
||||
|
||||
if (videoService.found(md)) {
|
||||
return videoService.offline();
|
||||
} else if (gistMarkdown(md)) {
|
||||
return gistService.offline();
|
||||
} else if (imageService.background(md)) {
|
||||
return imageService.buildBackgroundOffline(md);
|
||||
} else if (imageService.inline(md)) {
|
||||
|
||||
/*
|
||||
* Link found in markdown fragment, process.
|
||||
*/
|
||||
int delim = md.indexOf(MD_LINK_DELIM);
|
||||
|
||||
if (delim == NOT_FOUND) {
|
||||
|
||||
/*
|
||||
* Valid link syntax not found, return unmodified.
|
||||
*/
|
||||
return md;
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Valid link syntax found, now process link to
|
||||
* handle absolute, (GitHub) relative and video links.
|
||||
*/
|
||||
|
||||
String splitLeft = md.substring(0, delim + 2);
|
||||
String splitRight = md.substring(delim + 2);
|
||||
|
||||
/*
|
||||
* Clone and clean splitRight string to begin
|
||||
* extraction of the pitchLink.
|
||||
*/
|
||||
String pitchLink = cloneLink(splitRight);
|
||||
pitchLink = extractLink(pitchLink, null);
|
||||
|
||||
String imageName = FilenameUtils.getName(pitchLink);
|
||||
return imageService.buildInlineOffline(imageName);
|
||||
}
|
||||
} else if(imageService.tagFound(md)) {
|
||||
return imageService.buildTagOffline(md);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Link-free markdown, return unmodified.
|
||||
*/
|
||||
return md;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return image asset URL from Markdown fragment.
|
||||
*/
|
||||
public String offlineAssets(String md) {
|
||||
|
||||
if (imageService.background(md)) {
|
||||
|
||||
String frag = md.substring(MD_IMAGE_OPEN.length());
|
||||
String url = frag.substring(0, frag.indexOf("\""));
|
||||
return url;
|
||||
|
||||
} else if (imageService.inline(md)) {
|
||||
|
||||
/*
|
||||
* Link found in markdown fragment, process.
|
||||
*/
|
||||
|
||||
int delim = md.indexOf(MD_LINK_DELIM);
|
||||
|
||||
if (delim == NOT_FOUND) {
|
||||
|
||||
/*
|
||||
* Valid link syntax not found, return unmodified.
|
||||
*/
|
||||
return null;
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Valid link syntax found, now process link to
|
||||
* handle absolute, (GitHub) relative and video links.
|
||||
*/
|
||||
|
||||
String splitLeft = md.substring(0, delim + 2);
|
||||
String splitRight = md.substring(delim + 2);
|
||||
|
||||
/*
|
||||
* Clone and clean splitRight string to begin
|
||||
* extraction of the pitchLink.
|
||||
*/
|
||||
String pitchLink = cloneLink(splitRight);
|
||||
|
||||
int spaceIdx = pitchLink.indexOf(MD_LINK_SPACE);
|
||||
int brcktIdx = pitchLink.indexOf(MD_LINK_BRCKT);
|
||||
|
||||
String origLink = null;
|
||||
|
||||
if (spaceIdx == NOT_FOUND || spaceIdx > brcktIdx) {
|
||||
origLink = pitchLink.substring(0, brcktIdx);
|
||||
} else {
|
||||
origLink = pitchLink.substring(0, spaceIdx);
|
||||
}
|
||||
return origLink;
|
||||
}
|
||||
|
||||
} if(imageService.tagFound(md)) {
|
||||
/*
|
||||
* Img tag found in markdown fragment, process.
|
||||
*/
|
||||
return imageService.tagLink(md);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean imageDelimFound(DelimParams dp) {
|
||||
return dp.get(DELIM_QUERY_IMAGE) != null;
|
||||
}
|
||||
|
||||
private boolean videoDelimFound(DelimParams dp) {
|
||||
return dp.get(DELIM_QUERY_VIDEO) != null;
|
||||
}
|
||||
|
||||
private boolean gistDelimFound(DelimParams dp) {
|
||||
return dp.get(DELIM_QUERY_GIST) != null;
|
||||
}
|
||||
|
||||
private boolean codeDelimFound(DelimParams dp) {
|
||||
return dp.get(DELIM_QUERY_CODE) != null;
|
||||
}
|
||||
|
||||
private boolean colorDelimFound(DelimParams dp) {
|
||||
return dp.get(DELIM_QUERY_COLOR) != null;
|
||||
}
|
||||
|
||||
private String delimiter(String md) {
|
||||
return (md.startsWith(hSlideDelim)) ? horizDelim() : vertDelim();
|
||||
}
|
||||
|
||||
private boolean slideDelimFound(String md) {
|
||||
return md.startsWith(horizDelim()) || md.startsWith(vertDelim());
|
||||
}
|
||||
|
||||
private boolean markdownLinkFound(String md) {
|
||||
return md.startsWith(MD_LINK_OPEN);
|
||||
}
|
||||
|
||||
private boolean gistMarkdown(String md) {
|
||||
return md.contains(DATA_GIST_ATTR);
|
||||
}
|
||||
|
||||
private String cloneLink(String link) {
|
||||
|
||||
String cloned = new String(link);
|
||||
|
||||
/*
|
||||
* Strip slash prefix from relative links.
|
||||
*/
|
||||
if (cloned.startsWith(MD_LINK_SLASH)) {
|
||||
return cloned.substring(1);
|
||||
} else {
|
||||
return cloned;
|
||||
}
|
||||
}
|
||||
|
||||
private String extractLink(String link, String gitRawBase) {
|
||||
|
||||
try {
|
||||
|
||||
int spaceIdx = link.indexOf(MD_LINK_SPACE);
|
||||
int brcktIdx = link.indexOf(MD_LINK_BRCKT);
|
||||
|
||||
String origLink = null;
|
||||
|
||||
if (spaceIdx == NOT_FOUND || spaceIdx > brcktIdx) {
|
||||
origLink = link.substring(0, brcktIdx);
|
||||
} else {
|
||||
origLink = link.substring(0, spaceIdx);
|
||||
}
|
||||
|
||||
if (linkAbsolute(link)) {
|
||||
link = origLink;
|
||||
} else {
|
||||
link = gitRawBase + origLink;
|
||||
}
|
||||
|
||||
return link;
|
||||
|
||||
} catch (Exception lex) {
|
||||
log.warn("extractLink: link={}, ex={}", link, lex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String postProcess(String md,
|
||||
PitchParams pp,
|
||||
YAMLOptions yOpts,
|
||||
String gitRawBase) {
|
||||
|
||||
if (yOpts != null && yOpts.hasImageBg()) {
|
||||
|
||||
if (!delimOnFirstSlide(md)) {
|
||||
|
||||
/*
|
||||
* Inject slideshow-wide background for
|
||||
* implicit delim on first slide in the slideshow.
|
||||
*/
|
||||
md = imageService.buildBackground(pp, yOpts) + md;
|
||||
}
|
||||
}
|
||||
|
||||
if (delimOnFirstSlide(md)) {
|
||||
|
||||
int nIndex = md.indexOf(MD_SPACER);
|
||||
|
||||
if (nIndex > 0) {
|
||||
String slimMd = md.substring(nIndex);
|
||||
md = slimMd;
|
||||
}
|
||||
}
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
private boolean delimOnFirstSlide(String md) {
|
||||
return (md.startsWith(horizDelim()) || md.startsWith(vertDelim()));
|
||||
}
|
||||
|
||||
public boolean isHorizontal(String md) {
|
||||
return (md.startsWith(horizDelim())) ? true : false;
|
||||
}
|
||||
|
||||
public boolean linkAbsolute(String link) {
|
||||
return link.startsWith(MD_LINK_ABS);
|
||||
}
|
||||
|
||||
public String linkLive(PitchParams pp, String linkBase) {
|
||||
try {
|
||||
|
||||
linkBase = linkBase.replaceAll(MD_LINK_SPACE, ENCODED_SPACE);
|
||||
if (linkAbsolute(linkBase)) {
|
||||
return linkBase;
|
||||
} else {
|
||||
return grsManager.getService(grsManager.get(pp))
|
||||
.raw(pp, linkBase);
|
||||
}
|
||||
|
||||
} catch (Exception lex) {
|
||||
log.warn("linkLive: ex={}", lex);
|
||||
return "#";
|
||||
}
|
||||
}
|
||||
|
||||
public String extractDelim(String md) {
|
||||
return isHorizontal(md) ? horizDelim() : vertDelim();
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a key for querying the cache for matching MarkdownModel.
|
||||
*/
|
||||
public static String genKey(PitchParams pp) {
|
||||
|
||||
return new StringBuffer(MODEL_ID).append(SLASH)
|
||||
.append(pp.grs)
|
||||
.append(SLASH)
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.append(PARAM_BRANCH)
|
||||
.append(pp.branch)
|
||||
.append(PARAM_PITCHME)
|
||||
.append(pp.pitchme)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String horizDelim() {
|
||||
return hSlideDelim;
|
||||
}
|
||||
|
||||
public String vertDelim() {
|
||||
return vSlideDelim;
|
||||
}
|
||||
|
||||
public String horizImageDelim() {
|
||||
return horizDelim() + MD_HSLIDE_IMAGE;
|
||||
}
|
||||
|
||||
public String vertImageDelim() {
|
||||
return vertDelim() + MD_VSLIDE_IMAGE;
|
||||
}
|
||||
|
||||
public String horizVideoDelim() {
|
||||
return horizDelim() + MD_HSLIDE_VIDEO;
|
||||
}
|
||||
|
||||
public String vertVideoDelim() {
|
||||
return vertDelim() + MD_VSLIDE_VIDEO;
|
||||
}
|
||||
|
||||
public String horizGISTDelim() {
|
||||
return horizDelim() + MD_HSLIDE_GIST;
|
||||
}
|
||||
|
||||
public String vertGISTDelim() {
|
||||
return vertDelim() + MD_VSLIDE_GIST;
|
||||
}
|
||||
|
||||
public String horizCodeDelim() {
|
||||
return horizDelim() + MD_HSLIDE_CODE;
|
||||
}
|
||||
|
||||
public String vertCodeDelim() {
|
||||
return vertDelim() + MD_VSLIDE_CODE;
|
||||
}
|
||||
|
||||
/*
|
||||
* The initial releases of GitPitch used #HSLIDE and #VSLIDE
|
||||
* as default delimiters. To provide backwards compatability
|
||||
* for older presentations, when these old delimters are
|
||||
* detected within PITCHME.md we auto-translate these old
|
||||
* delimiters to the current defaults HSLIDE|VSLIDE_DELIM_DEFAULT.
|
||||
*/
|
||||
private String processBackwardCompatDelim(String md) {
|
||||
try {
|
||||
if(md.startsWith(HSLIDE_DELIM_BACK_COMPAT)) {
|
||||
md = md.replaceFirst(HSLIDE_DELIM_BACK_COMPAT,
|
||||
HSLIDE_DELIM_DEFAULT);
|
||||
} else
|
||||
if(md.startsWith(VSLIDE_DELIM_BACK_COMPAT)) {
|
||||
md = md.replaceFirst(VSLIDE_DELIM_BACK_COMPAT,
|
||||
VSLIDE_DELIM_DEFAULT);
|
||||
}
|
||||
|
||||
} catch(Exception bcex) {
|
||||
return md;
|
||||
}
|
||||
return md;
|
||||
}
|
||||
|
||||
/*
|
||||
* Markdown Parsing Identifiers | Delimiters.
|
||||
*/
|
||||
public static final String HSLIDE_DELIM_DEFAULT = "---";
|
||||
public static final String VSLIDE_DELIM_DEFAULT = "+++";
|
||||
public static final String HSLIDE_REGEX_DEFAULT = null;
|
||||
public static final String VSLIDE_REGEX_DEFAULT = "\\+\\+\\+";
|
||||
|
||||
public static final String HSLIDE_DELIM_BACK_COMPAT = "#HSLIDE";
|
||||
public static final String VSLIDE_DELIM_BACK_COMPAT = "#VSLIDE";
|
||||
|
||||
public static final String DELIM_QUERY_IMAGE = "image";
|
||||
public static final String DELIM_QUERY_VIDEO = "video";
|
||||
public static final String DELIM_QUERY_LOOP = "loop";
|
||||
public static final String DELIM_QUERY_MUTED = "muted";
|
||||
public static final String DELIM_QUERY_GIST = "gist";
|
||||
public static final String DELIM_QUERY_CODE = "code";
|
||||
public static final String DELIM_QUERY_LANG = "lang";
|
||||
public static final String DELIM_QUERY_SIZE = "size";
|
||||
public static final String DELIM_QUERY_COLOR = "color";
|
||||
public static final String DELIM_QUERY_POSITION = "position";
|
||||
public static final String DELIM_QUERY_REPEAT = "repeat";
|
||||
public static final String DELIM_QUERY_TRANSITION = "transition";
|
||||
public static final String DELIM_QUERY_FILE = "file";
|
||||
public static final String DELIM_QUERY_TITLE = "title";
|
||||
|
||||
public static final String MD_LINK_OPEN = "![";
|
||||
public static final String MD_ANCHOR_OPEN = "[";
|
||||
public static final String MD_IMAGE_OPEN =
|
||||
"<!-- .slide: data-background-image=\"";
|
||||
public static final String MD_VIDEO_OPEN =
|
||||
"<!-- .slide: data-background-video=\"";
|
||||
public static final String MD_VIDEO_OPEN_END = "\" ";
|
||||
public static final String MD_VIDEO_LOOP =
|
||||
" data-background-video-loop=\"true\" ";
|
||||
public static final String MD_VIDEO_MUTED =
|
||||
" data-background-video-muted=\"true\" ";
|
||||
public static final String MD_VIDEO_CLOSE = " -->";
|
||||
public static final String MD_IFRAME_OPEN =
|
||||
"<!-- .slide: data-background-iframe=\"";
|
||||
public static final String MD_IMAGE_SIZE =
|
||||
"\" data-background-size=\"";
|
||||
public static final String MD_IMAGE_COLOR =
|
||||
"\" data-background-color=\"";
|
||||
public static final String MD_IMAGE_POSITION =
|
||||
"\" data-background-position=\"";
|
||||
public static final String MD_IMAGE_REPEAT =
|
||||
"\" data-background-repeat=\"";
|
||||
public static final String MD_IMAGE_TRANSITION =
|
||||
"\" data-background-transition=\"";
|
||||
public static final String MD_BG_COLOR =
|
||||
"<!-- .slide: data-background=\"";
|
||||
public static final String MD_CLOSER = "\" -->";
|
||||
public static final String MD_SPACER = "\n";
|
||||
public static final String DATA_IMAGE_ATTR = "data-background-image=";
|
||||
public static final String MD_LIST_FRAG_OPEN = "- ";
|
||||
public static final String MD_LIST_FRAG_CLOSE = "|";
|
||||
public static final String MD_CODE_FRAG_OPEN = "@[";
|
||||
public static final String MD_CODE_FRAG_CLOSE = "]";
|
||||
public static final String MD_CODE_FRAG_NOTE_OPEN = "(";
|
||||
public static final String MD_CODE_FRAG_NOTE_CLOSE = ")";
|
||||
public static final String MD_CODE_BLOCK_OPEN = "```";
|
||||
public static final String MD_CODE_BLOCK_CLOSE = "```";
|
||||
public static final String MD_TITLE_HINT_OPEN = "@title[";
|
||||
public static final String MD_TITLE_HINT_CLOSE = "]";
|
||||
public static final String MD_FA_OPEN = "@fa[";
|
||||
public static final String MD_FA_CLOSE = "]";
|
||||
public static final String MD_FA_NOTE_OPEN = "(";
|
||||
public static final String MD_FA_NOTE_CLOSE = ")";
|
||||
|
||||
private static final String MD_HSLIDE_IMAGE = "?image=";
|
||||
private static final String MD_VSLIDE_IMAGE = "?image=";
|
||||
private static final String MD_HSLIDE_VIDEO = "?video=";
|
||||
private static final String MD_VSLIDE_VIDEO = "?video=";
|
||||
private static final String MD_HSLIDE_GIST = "?gist=";
|
||||
private static final String MD_VSLIDE_GIST = "?gist=";
|
||||
private static final String MD_HSLIDE_CODE = "?code=";
|
||||
private static final String MD_VSLIDE_CODE = "?code=";
|
||||
|
||||
private static final String SLASH = "/";
|
||||
private static final String PARAM_BRANCH = "?b=";
|
||||
private static final String PARAM_PITCHME = "&p=";
|
||||
private static final String MD_LINK_DELIM = "](";
|
||||
private static final String MD_LINK_ABS = "http";
|
||||
private static final String MD_LINK_SLASH = "/";
|
||||
private static final String MD_LINK_SPACE = " ";
|
||||
private static final String MD_LINK_BRCKT = ")";
|
||||
private static final String MD_LINK_MP4 = "mp4";
|
||||
private static final String DATA_GIST_ATTR = "data-gist=";
|
||||
private static final String HTML_ANCHOR_OPEN =
|
||||
"<a target=\"_blank\" href=\"";
|
||||
private static final String HTML_ANCHOR_MID = "\">";
|
||||
private static final String HTML_ANCHOR_CLOSE = "</a>";
|
||||
private static final int NOT_FOUND = -1;
|
||||
private static final String ENCODED_SPACE = "%20";
|
||||
/*
|
||||
* Model prefix identifier for cache key generator.
|
||||
*/
|
||||
private static final String MODEL_ID = "MDM:";
|
||||
private static final String PITCHME_MD = "PITCHME.md";
|
||||
}
|
|
@ -1,643 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.models;
|
||||
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.git.GRSService;
|
||||
import com.gitpitch.services.DiskService;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.utils.YAMLOptions;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* Rendering model for views.Slideshow.scala.html.
|
||||
*/
|
||||
public class SlideshowModel {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
/*
|
||||
* Parameter values passed on GitPitch API call.
|
||||
*/
|
||||
private final PitchParams _pp;
|
||||
/*
|
||||
* PITCHME.yaml options.
|
||||
*/
|
||||
private final YAMLOptions _yOpts;
|
||||
/*
|
||||
* GitPitch API /api/markdown/{user}/{repo}?b={branch}.
|
||||
*/
|
||||
private final String _fetchMarkdown;
|
||||
/*
|
||||
* Derived immutable state.
|
||||
*/
|
||||
private final String _pretty;
|
||||
private final String _cacheKey;
|
||||
|
||||
private SlideshowModel(PitchParams pp,
|
||||
YAMLOptions yOpts) {
|
||||
|
||||
this._pp = pp;
|
||||
this._yOpts = yOpts;
|
||||
|
||||
this._fetchMarkdown =
|
||||
com.gitpitch.controllers.routes.PitchController.markdown(pp.grs,
|
||||
pp.user,
|
||||
pp.repo,
|
||||
pp.branch,
|
||||
pp.pitchme).url();
|
||||
|
||||
this._pretty = new StringBuffer(SLASH)
|
||||
.append(this._pp.user)
|
||||
.append(SLASH)
|
||||
.append(this._pp.repo)
|
||||
.append(PARAM_BRANCH)
|
||||
.append(this._pp.branch)
|
||||
.append(PARAM_PITCHME)
|
||||
.append(this._pp.pitchme)
|
||||
.toString();
|
||||
|
||||
this._cacheKey = genKey(pp);
|
||||
}
|
||||
|
||||
public static SlideshowModel build(PitchParams pp,
|
||||
boolean yamlFound,
|
||||
GRSService grsService,
|
||||
DiskService diskService) {
|
||||
|
||||
YAMLOptions yOpts =
|
||||
yamlFound ? YAMLOptions.build(pp, grsService, diskService) : null;
|
||||
return new SlideshowModel(pp, yOpts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a key for querying the cache for matching SlideshowModel.
|
||||
*/
|
||||
public static String genKey(PitchParams pp) {
|
||||
|
||||
return new StringBuffer(MODEL_ID).append(SLASH)
|
||||
.append(pp.grs)
|
||||
.append(SLASH)
|
||||
.append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.append(PARAM_BRANCH)
|
||||
.append(pp.branch)
|
||||
.append(PARAM_PITCHME)
|
||||
.append(pp.pitchme)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public SlideshowModel clone(PitchParams pp) {
|
||||
return new SlideshowModel(pp, this._yOpts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return PitchParams instance on SlideshowModel.
|
||||
*/
|
||||
public PitchParams params() {
|
||||
return _pp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return YAMLOptions instance on SlideshowModel.
|
||||
*/
|
||||
public YAMLOptions options() {
|
||||
return _yOpts;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if custom theme in use.
|
||||
*/
|
||||
public boolean fixedTheme() {
|
||||
return (_yOpts != null) ?
|
||||
_yOpts.fixedTheme(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return active theme name for slideshow.
|
||||
*/
|
||||
public String fetchTheme() {
|
||||
|
||||
return (_yOpts != null) ? _yOpts.fetchTheme(params()) :
|
||||
_pp.theme;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return active theme.css for slideshow.
|
||||
*/
|
||||
public String fetchThemeCSS() {
|
||||
|
||||
return (_yOpts != null) ? _yOpts.fetchThemeCSS(params()) :
|
||||
PitchParams.fetchThemeCSS(_pp.theme);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return theme override css for slideshow.
|
||||
*/
|
||||
public boolean hasThemeOverride() {
|
||||
|
||||
return (_yOpts != null) ?
|
||||
_yOpts.hasThemeOverride(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return theme override css for slideshow.
|
||||
*/
|
||||
public String fetchThemeOverride() {
|
||||
|
||||
String customCSS = null;
|
||||
|
||||
if(hasThemeOverride()) {
|
||||
String oride = _yOpts.fetchThemeOverride(params());
|
||||
try {
|
||||
customCSS = IOUtils.toString(new URL(oride),
|
||||
Charset.forName("UTF-8"));
|
||||
} catch(Exception ioex) {}
|
||||
}
|
||||
log.debug("fetchThemeOverride: customCSS={}", customCSS);
|
||||
return customCSS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return active theme font for slideshow.
|
||||
*/
|
||||
public String fetchThemeFont() {
|
||||
|
||||
String font = THEME_FONTS.get(fetchTheme());
|
||||
return (font != null) ? font : THEME_FONT_DEFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return active theme font color inverse for slideshow.
|
||||
*/
|
||||
public String fetchThemeFontColorInverse() {
|
||||
|
||||
boolean darkTheme = PitchParams.isDarkTheme(fetchTheme());
|
||||
return darkTheme ? THEME_DARK_COLOR_INVERSE :
|
||||
THEME_LIGHT_COLOR_INVERSE;
|
||||
}
|
||||
|
||||
public boolean isDarkTheme() {
|
||||
return PitchParams.isDarkTheme(fetchTheme());
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if "layout" in *-left.
|
||||
*/
|
||||
public boolean isLeftLayout() {
|
||||
return (_yOpts != null) ? _yOpts.isLeftLayout(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if "layout" in *-right.
|
||||
*/
|
||||
public boolean isRightLayout() {
|
||||
return (_yOpts != null) ? _yOpts.isRightLayout(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if "logo" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean hasLogo() {
|
||||
|
||||
return (_yOpts != null) ? _yOpts.hasLogo() : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "logo" defined in PITCHME.yaml.
|
||||
*/
|
||||
public String fetchLogo() {
|
||||
return (_yOpts != null) ? _yOpts.fetchLogo(params()) : "#";
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "logo" filename defined in PITCHME.yaml.
|
||||
*/
|
||||
public String fetchLogoName() {
|
||||
return (_yOpts != null) ?
|
||||
FilenameUtils.getName(_yOpts.fetchLogo(params())) : "#";
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "logo-position" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean hasLogoPosition() {
|
||||
return (_yOpts != null) ? _yOpts.hasLogoPosition() : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "logo-position" defined in PITCHME.yaml.
|
||||
*/
|
||||
public String fetchLogoPosition() {
|
||||
String position = _yOpts.fetchLogoPosition(params());
|
||||
return LOGO_POSITIONS.get(position);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if "footnote" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean hasFootnote() {
|
||||
|
||||
return (_yOpts != null) ? _yOpts.hasFootnote(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "footnote" defined in PITCHME.yaml.
|
||||
*/
|
||||
public String fetchFootnote() {
|
||||
return (_yOpts != null) ?
|
||||
_yOpts.fetchFootnote(params()) : "Footnote undefined.";
|
||||
}
|
||||
|
||||
/*
|
||||
* Return markdown for slideshow.
|
||||
*/
|
||||
public String fetchMarkdown() {
|
||||
return _fetchMarkdown;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if slideshow speaker notes should be displayed.
|
||||
*/
|
||||
public boolean showNotes() {
|
||||
return (_pp != null) ? Boolean.parseBoolean(_pp.notes) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "transition" defined in PITCHME.yaml.
|
||||
*/
|
||||
public String fetchTransition() {
|
||||
return (_yOpts != null) ? _yOpts.fetchTransition(params()) :
|
||||
YAMLOptions.DEFAULT_TRANSITION;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "controls-layout" defined in PITCHME.yaml.
|
||||
*/
|
||||
public String fetchControlsLayout() {
|
||||
|
||||
String layout = (_yOpts != null) ?
|
||||
_yOpts.fetchControlsLayout(params()) :
|
||||
YAMLOptions.DEFAULT_CONTROLS_LAYOUT;
|
||||
|
||||
// Auto-relocate controls to 'edges' if logo-position is bottom-right.
|
||||
if(_yOpts != null && hasLogoPosition()) {
|
||||
String position = _yOpts.fetchLogoPosition(params());
|
||||
if(YAMLOptions.DEFAULT_CONTROLS_LAYOUT.equals(position)) {
|
||||
layout = YAMLOptions.EDGES_CONTROLS_LAYOUT;
|
||||
}
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "autoslide" defined in PITCHME.yaml.
|
||||
*/
|
||||
public int fetchAutoSlide(boolean printing) {
|
||||
|
||||
if(printing)
|
||||
return 0; // Disable auto-slide when printing.
|
||||
else
|
||||
return (_yOpts != null) ? _yOpts.fetchAutoSlide(params()) : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "vertical-center" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean fetchVerticalCenter() {
|
||||
|
||||
boolean vc = true;
|
||||
|
||||
if(_yOpts == null) {
|
||||
vc = true;
|
||||
} else
|
||||
if(_yOpts.isTopLayout(params())) {
|
||||
vc = false;
|
||||
} else {
|
||||
vc = _yOpts.fetchVerticalCenter(params());
|
||||
}
|
||||
return vc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "loop" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean fetchLoop() {
|
||||
return (_yOpts != null) ? _yOpts.fetchLoop(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "remote-control" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean remoteControlEnabled() {
|
||||
return (_yOpts != null) ? _yOpts.fetchRemoteControl(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "remote-control-prevkey" defined in PITCHME.yaml.
|
||||
*/
|
||||
public int remoteControlPrevKey() {
|
||||
int prevKeyCode = DEFAULT_PREV_KEYCODE;
|
||||
if(_yOpts != null) {
|
||||
prevKeyCode = _yOpts.fetchRemoteControlPrevKey(params());
|
||||
}
|
||||
return prevKeyCode != 0 ? prevKeyCode : DEFAULT_PREV_KEYCODE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "remote-control-nextkey" defined in PITCHME.yaml.
|
||||
*/
|
||||
public int remoteControlNextKey() {
|
||||
int nextKeyCode = DEFAULT_NEXT_KEYCODE;
|
||||
if(_yOpts != null) {
|
||||
nextKeyCode = _yOpts.fetchRemoteControlNextKey(params());
|
||||
}
|
||||
return nextKeyCode != 0 ? nextKeyCode : DEFAULT_NEXT_KEYCODE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "rtl" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean fetchRTL() {
|
||||
return (_yOpts != null) ? _yOpts.fetchRTL(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "shuffle" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean fetchShuffle() {
|
||||
return (_yOpts != null) ? _yOpts.fetchShuffle(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "mousewheel" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean fetchMouseWheel() {
|
||||
return (_yOpts != null) ? _yOpts.fetchMouseWheel(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if "charts" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean chartsEnabled() {
|
||||
return (_yOpts != null) ? _yOpts.fetchCharts(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if "mathjax" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean mathEnabled() {
|
||||
return (_yOpts != null) ? _yOpts.mathEnabled(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "history" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean fetchHistory() {
|
||||
return (_yOpts != null) ? _yOpts.fetchHistory(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "slide-number" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean fetchSlideNumber() {
|
||||
return (_yOpts != null) ? _yOpts.fetchSlideNumber(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "mathjax" defined in PITCHME.yaml.
|
||||
*/
|
||||
public String fetchMathConfig() {
|
||||
return (_yOpts != null) ? _yOpts.mathConfig(params()) :
|
||||
YAMLOptions.MATHJAX_DEFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return active theme.css for slideshow.
|
||||
*/
|
||||
public String fetchHighlightCSS() {
|
||||
|
||||
if (_yOpts != null) {
|
||||
return _yOpts.fetchHighlight(params());
|
||||
} else {
|
||||
return _pp.darkTheme() ?
|
||||
YAMLOptions.HIGHLIGHT_DARK_DEFAULT :
|
||||
YAMLOptions.HIGHLIGHT_LIGHT_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if "published" set to true in PITCHME.yaml.
|
||||
*/
|
||||
public boolean published() {
|
||||
|
||||
return (_yOpts != null) ? _yOpts.published(_pp) : false;
|
||||
}
|
||||
|
||||
public String fetchHorzDelim() {
|
||||
|
||||
String delim = null;
|
||||
|
||||
if(_yOpts != null && _yOpts.hasHorzDelim(params())) {
|
||||
|
||||
String regexp = _yOpts.fetchHorzDelimRegExp(params());
|
||||
delim = (regexp != null) ? buildSlideDelim(regexp) :
|
||||
buildSlideDelim(_yOpts.fetchHorzDelim(params()));
|
||||
log.debug("fetchHorzDelim: custom delim={}", delim);
|
||||
}
|
||||
|
||||
if(delim == null) {
|
||||
if(MarkdownModel.HSLIDE_REGEX_DEFAULT != null)
|
||||
delim = buildSlideDelim(MarkdownModel.HSLIDE_REGEX_DEFAULT);
|
||||
else
|
||||
delim = buildSlideDelim(MarkdownModel.HSLIDE_DELIM_DEFAULT);
|
||||
}
|
||||
return delim;
|
||||
}
|
||||
|
||||
public String fetchVertDelim() {
|
||||
|
||||
String delim = null;
|
||||
|
||||
if(_yOpts != null && _yOpts.hasVertDelim(params())) {
|
||||
|
||||
String regexp = _yOpts.fetchVertDelimRegExp(params());
|
||||
log.debug("fetchVertDelim: regexp={}", regexp);
|
||||
delim = (regexp != null) ? buildSlideDelim(regexp) :
|
||||
buildSlideDelim(_yOpts.fetchVertDelim(params()));
|
||||
log.debug("fetchVertDelim: custom delim={}", delim);
|
||||
}
|
||||
|
||||
if(delim == null) {
|
||||
if(MarkdownModel.VSLIDE_REGEX_DEFAULT != null)
|
||||
delim = buildSlideDelim(MarkdownModel.VSLIDE_REGEX_DEFAULT);
|
||||
else
|
||||
delim = buildSlideDelim(MarkdownModel.VSLIDE_DELIM_DEFAULT);
|
||||
}
|
||||
return delim;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if "gatoken" defined in PITCHME.yaml.
|
||||
*/
|
||||
public boolean hasGAToken() {
|
||||
|
||||
return (_yOpts != null) ? _yOpts.hasGAToken(params()) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "gatoken" defined in PITCHME.yaml.
|
||||
*/
|
||||
public String fetchGAToken() {
|
||||
return (_yOpts != null) ?
|
||||
_yOpts.fetchGAToken(params()) : null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return "revealjs-version" override for slideshow.
|
||||
*/
|
||||
public String fetchRevealVersionOverride() {
|
||||
return (_yOpts != null) ?
|
||||
_yOpts.fetchRevealVersion(params()) : null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return presentation Help message.
|
||||
*/
|
||||
public String fetchHelp(boolean smallScreen) {
|
||||
return smallScreen ? SMALL_HELP : HELP;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return _pretty;
|
||||
}
|
||||
|
||||
public String key() {
|
||||
return _cacheKey;
|
||||
}
|
||||
|
||||
public String homePanel() {
|
||||
return com.gitpitch.controllers.routes.PitchController.home(_pp.grs,
|
||||
_pp.user,
|
||||
_pp.repo,
|
||||
_pp.branch,
|
||||
_pp.theme,
|
||||
_pp.pitchme,
|
||||
"false").toString();
|
||||
}
|
||||
|
||||
public String gitPanel() {
|
||||
return com.gitpitch.controllers.routes.PitchController.git(_pp.grs,
|
||||
_pp.user,
|
||||
_pp.repo,
|
||||
_pp.branch,
|
||||
_pp.theme,
|
||||
_pp.pitchme,
|
||||
null).toString();
|
||||
}
|
||||
|
||||
public String themesPanel() {
|
||||
return com.gitpitch.controllers.routes.PitchController.themes(_pp.grs,
|
||||
_pp.user,
|
||||
_pp.repo,
|
||||
_pp.branch,
|
||||
_pp.theme,
|
||||
_pp.pitchme,
|
||||
null).toString();
|
||||
}
|
||||
|
||||
private String buildSlideDelim(String pattern) {
|
||||
|
||||
log.debug("buildSlideDelim: pattern={}", pattern);
|
||||
|
||||
return new StringBuffer("(^").append(pattern)
|
||||
.append("$|^")
|
||||
.append(pattern)
|
||||
.append("\\?.*)")
|
||||
.toString();
|
||||
}
|
||||
|
||||
private static final String SLASH = "/";
|
||||
private static final String PARAM_BRANCH = "?b=";
|
||||
private static final String PARAM_PITCHME = "&p=";
|
||||
private static final String PITCHME_YAML = "PITCHME.yaml";
|
||||
/*
|
||||
* Model prefix identifier for cache key generator.
|
||||
*/
|
||||
private static final String MODEL_ID = "SSM:";
|
||||
private static final Integer DEFAULT_PREV_KEYCODE = 37;
|
||||
private static final Integer DEFAULT_NEXT_KEYCODE = 39;
|
||||
private static final String THEME_FONT_DEFAULT =
|
||||
"Source Sans Pro, Helvetica, sans-serif";
|
||||
private static final String THEME_DARK_COLOR_INVERSE = "white";
|
||||
private static final String THEME_LIGHT_COLOR_INVERSE = "black";
|
||||
private static Map<String, String> THEME_FONTS =
|
||||
Collections.unmodifiableMap(new HashMap<String, String>() {
|
||||
{
|
||||
put("black", "Source Sans Pro, Helvetica, sans-serif");
|
||||
put("moon", "Lato, sans-serif");
|
||||
put("night", "Open Sans, sans-serif");
|
||||
put("beige", "Lato, sans-serif");
|
||||
put("sky", "Open Sans, sans-serif");
|
||||
put("white", "Source Sans Pro, Helvetica, sans-serif");
|
||||
}
|
||||
});
|
||||
private static Map<String, String> LOGO_POSITIONS =
|
||||
Collections.unmodifiableMap(new HashMap<String, String>() {
|
||||
{
|
||||
put("top-left", "position: fixed; top: 20px; left: 20px; z-index: 1");
|
||||
put("top-right", "position: fixed; top: 20px; right: 20px; z-index: 1");
|
||||
put("bottom-left", "position: fixed; bottom: 20px; left: 20px; z-index: 1");
|
||||
put("bottom-right", "position: fixed; bottom: 20px; right: 20px; z-index: 1");
|
||||
}
|
||||
});
|
||||
|
||||
private static final String HELP =
|
||||
"Navigate : Space / Arrow Keys | " +
|
||||
"<a href='#' onclick='RevealMenu.toggle()'>M</a> - Menu | " +
|
||||
"<a href='#' onclick='enterFullscreen()'>F</a> - Fullscreen | " +
|
||||
"<a href='#' onclick='enterOverview()'>O</a> - Overview | " +
|
||||
"<a href='#' onclick='enterBlackout()'>B</a> - Blackout | " +
|
||||
"<a href='#' onclick='RevealNotes.open()'>S</a> - Speaker | " +
|
||||
"<a href='#' onclick='enterHelp()'>?</a> - Help";
|
||||
|
||||
private static final String SMALL_HELP =
|
||||
"<a href='#' onclick='RevealMenu.toggle()'>Menu</a> | " +
|
||||
"<a href='#' onclick='enterFullscreen()'>Fullscreen</a> | " +
|
||||
"<a href='#' onclick='enterOverview()'>Overview</a> | " +
|
||||
"<a href='#' onclick='enterBlackout()'>Blackout</a> | " +
|
||||
"<a href='#' onclick='RevealNotes.open()'>Speaker</a> | " +
|
||||
"<a href='#' onclick='enterHelp()'>Help</a>";
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.oembed;
|
||||
|
||||
import com.gitpitch.utils.PitchLink;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.git.GRSManager;
|
||||
import com.gitpitch.git.GRSService;
|
||||
|
||||
/*
|
||||
* GitPitch oEmbed Provider.
|
||||
*
|
||||
* https://oembed.com
|
||||
*/
|
||||
public class PitchEmbed {
|
||||
|
||||
public String title;
|
||||
public String author_name;
|
||||
public String html;
|
||||
|
||||
public String type = TYPE;
|
||||
public String version = VERSION;
|
||||
public String provider_name = GITPITCH;
|
||||
public String provider_url = GITPITCH_URL;
|
||||
public String cache_age = CACHE;
|
||||
public String width = DEFAULT_WIDTH;
|
||||
public String height = DEFAULT_HEIGHT;
|
||||
public String author_url;
|
||||
public String thumbnail_url = DEFAULT_THUMB;
|
||||
public String thumbnail_width;
|
||||
public String thumbnail_height;
|
||||
|
||||
public static PitchEmbed build(GRSManager grsManager,
|
||||
String url) {
|
||||
return build(grsManager,
|
||||
url,
|
||||
DEFAULT_WIDTH,
|
||||
DEFAULT_HEIGHT,
|
||||
null, null);
|
||||
}
|
||||
|
||||
public static PitchEmbed build(GRSManager grsManager,
|
||||
String url,
|
||||
String width,
|
||||
String height,
|
||||
String maxWidth,
|
||||
String maxHeight) {
|
||||
|
||||
PitchLink pl = PitchLink.build(url);
|
||||
PitchParams pp = PitchParams.build(pl.grs, pl.user, pl.repo, pl.branch);
|
||||
String authorUrl = grsManager.get(pp).getSite();
|
||||
authorUrl = new StringBuffer(authorUrl).append(pp.user)
|
||||
.append(SLASH)
|
||||
.append(pp.repo)
|
||||
.toString();
|
||||
return new PitchEmbed(pp,
|
||||
pl,
|
||||
authorUrl,
|
||||
width,
|
||||
height,
|
||||
maxWidth,
|
||||
maxHeight);
|
||||
}
|
||||
|
||||
private PitchEmbed(PitchParams pp,
|
||||
PitchLink pl,
|
||||
String authorUrl,
|
||||
String width,
|
||||
String height,
|
||||
String maxWidth,
|
||||
String maxHeight) {
|
||||
|
||||
this.title = buildTitle(pp);
|
||||
this.author_name = pl.user;
|
||||
this.author_url = authorUrl;
|
||||
this.width = buildWidth(width, maxWidth, maxHeight);
|
||||
this.height = buildHeight(height, maxWidth, maxHeight);
|
||||
this.thumbnail_width = this.width;
|
||||
this.thumbnail_height = this.height;
|
||||
this.html = buildHTML(pl.url, this.width, this.height);
|
||||
}
|
||||
|
||||
private String buildTitle(PitchParams pp) {
|
||||
return GITPITCH_PRESENTS + pp.pretty().substring(1);
|
||||
}
|
||||
|
||||
private String buildWidth(String width,
|
||||
String maxWidth,
|
||||
String maxHeight) {
|
||||
if(maxWidth != null)
|
||||
return maxWidth;
|
||||
if(maxHeight != null) {
|
||||
try {
|
||||
/*
|
||||
* Maintain aspect ratio [ 1.38 : 1 ] [ 960px : 700px ].
|
||||
*/
|
||||
int maxH = Integer.parseInt(maxHeight);
|
||||
return String.valueOf((int) Math.round(maxH * 1.38));
|
||||
} catch(Exception ex) {}
|
||||
}
|
||||
return (width != null) ? width : DEFAULT_WIDTH;
|
||||
}
|
||||
|
||||
private String buildHeight(String height,
|
||||
String maxWidth,
|
||||
String maxHeight) {
|
||||
if(maxHeight != null)
|
||||
return maxHeight;
|
||||
if(maxWidth != null) {
|
||||
try {
|
||||
/*
|
||||
* Maintain aspect ratio [ 1 : 0.73 ] [ 960px : 700px ].
|
||||
*/
|
||||
int maxW = Integer.parseInt(maxWidth);
|
||||
return String.valueOf((int) Math.round(maxW * 0.73));
|
||||
} catch(Exception ex) {}
|
||||
}
|
||||
return (height != null) ? height : DEFAULT_HEIGHT;
|
||||
}
|
||||
|
||||
private String buildHTML(String url, String width, String height) {
|
||||
|
||||
return new StringBuffer(HTML_OPEN).append(HTML_WIDTH)
|
||||
.append(width)
|
||||
.append(HTML_HEIGHT)
|
||||
.append(height)
|
||||
.append(HTML_SRC)
|
||||
.append(url)
|
||||
.append(HTML_BORDER)
|
||||
.append(HTML_MARGINS)
|
||||
.append(HTML_SCROLL)
|
||||
.append(HTML_CLOSE)
|
||||
.toString();
|
||||
}
|
||||
|
||||
private final static String GITPITCH = "GitPitch";
|
||||
private final static String GITPITCH_PRESENTS = "GitPitch Presents: ";
|
||||
private final static String GITPITCH_URL = "https://gitpitch.com";
|
||||
private final static String TYPE = "rich";
|
||||
private final static String VERSION = "1.0";
|
||||
private final static String CACHE = "180";
|
||||
private final static String DEFAULT_WIDTH = "960";
|
||||
private final static String DEFAULT_HEIGHT = "700";
|
||||
private final static String DEFAULT_THUMB =
|
||||
"https://gitpitch.com/gitpitch-icon-black.jpg";
|
||||
|
||||
private final static String HTML_OPEN = "<iframe ";
|
||||
private final static String HTML_WIDTH = "width=\"";
|
||||
private final static String HTML_HEIGHT = "\" height=\"";
|
||||
private final static String HTML_SRC = "\" src=\"";
|
||||
private final static String HTML_BORDER = "\" frameborder=\"0\" ";
|
||||
private final static String HTML_MARGINS =
|
||||
"marginwidth=\"0\" marginheight=\"0\" ";
|
||||
private final static String HTML_SCROLL = "scrolling=\"no\"";
|
||||
private final static String HTML_CLOSE = " allowfullscreen></iframe>";
|
||||
private final static String SLASH = "/";
|
||||
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.policies;
|
||||
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import javax.inject.*;
|
||||
|
||||
/*
|
||||
* GitPitch Cache Timeout Policies.
|
||||
*
|
||||
* Content in master is considered stable so typically
|
||||
* uses longer timeouts. Content in feature branches is
|
||||
* considered under development so shorter timeouts
|
||||
* are used to ensure changes are reflected quickly.
|
||||
*/
|
||||
@Singleton
|
||||
public class CacheTimeout {
|
||||
|
||||
/*
|
||||
* Return cache timeout in seconds for GitRepoModel.
|
||||
*/
|
||||
public int grm(PitchParams pp) {
|
||||
if (pp.isLongLived()) {
|
||||
return pp.isMaster() ? LL_MASTER_TIMEOUT : LL_BRANCH_TIMEOUT;
|
||||
} else {
|
||||
return pp.isMaster() ? GRM_MASTER_TIMEOUT : GRM_BRANCH_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return cache timeout in seconds for SlideshowModel.
|
||||
*/
|
||||
public int ssm(PitchParams pp) {
|
||||
if (pp.isLongLived()) {
|
||||
return pp.isMaster() ? LL_MASTER_TIMEOUT : LL_BRANCH_TIMEOUT;
|
||||
} else {
|
||||
return pp.isMaster() ? SSM_MASTER_TIMEOUT : SSM_BRANCH_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return cache timeout in seconds for MarkdownModel.
|
||||
*/
|
||||
public int mdm(PitchParams pp) {
|
||||
if (pp.isLongLived()) {
|
||||
return pp.isMaster() ? LL_MASTER_TIMEOUT : LL_BRANCH_TIMEOUT;
|
||||
} else {
|
||||
return pp.isMaster() ? MDM_MASTER_TIMEOUT : MDM_BRANCH_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return cache timeout in milliseconds for print PDF file.
|
||||
*/
|
||||
public long pdf(PitchParams pp) {
|
||||
return pp.isMaster() ? PDF_CACHE_MAX_AGE_MASTER : PDF_CACHE_MAX_AGE_BRANCH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return cache timeout in milliseconds for offline ZIP file.
|
||||
*/
|
||||
public long zip(PitchParams pp) {
|
||||
return pp.isMaster() ? ZIP_CACHE_MAX_AGE_MASTER : ZIP_CACHE_MAX_AGE_BRANCH;
|
||||
}
|
||||
|
||||
/*
|
||||
* PDF generation cache timeouts (ms) for PITCHME.pdf.
|
||||
*/
|
||||
public static final long PDF_CACHE_MAX_AGE_MASTER = 60 * 1000 * 20;
|
||||
public static final long PDF_CACHE_MAX_AGE_BRANCH = 20 * 1000;
|
||||
/*
|
||||
* Offline generation cache timeouts (ms) for PITCHME.zip.
|
||||
*/
|
||||
public static final long ZIP_CACHE_MAX_AGE_MASTER = 60 * 1000 * 20;
|
||||
public static final long ZIP_CACHE_MAX_AGE_BRANCH = 20 * 1000;
|
||||
/*
|
||||
* Long Lived cache timeouts (sec) for GitPitch-owned repos.
|
||||
*/
|
||||
private static final int LL_MASTER_TIMEOUT = 60 * 60;
|
||||
private static final int LL_BRANCH_TIMEOUT = 15;
|
||||
/*
|
||||
* GitRepoModel cache timeouts (sec) for GitHub repo meta-data.
|
||||
*/
|
||||
private static final int GRM_MASTER_TIMEOUT = 60 * 30;
|
||||
private static final int GRM_BRANCH_TIMEOUT = 60 * 30;
|
||||
/*
|
||||
* SlideshowModel cache timeouts (sec) for PITCHME.[css|jpg].
|
||||
*/
|
||||
private static final int SSM_MASTER_TIMEOUT = 15;
|
||||
private static final int SSM_BRANCH_TIMEOUT = 15;
|
||||
/*
|
||||
* MarkdownModel cache timeouts (sec) for PITCHME.md.
|
||||
*/
|
||||
private static final int MDM_MASTER_TIMEOUT = SSM_MASTER_TIMEOUT;
|
||||
private static final int MDM_BRANCH_TIMEOUT = SSM_BRANCH_TIMEOUT;
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.policies;
|
||||
|
||||
import com.gitpitch.policies.Runtime;
|
||||
import javax.inject.*;
|
||||
|
||||
/*
|
||||
* External dependency manager for the GitPitch server.
|
||||
*/
|
||||
@Singleton
|
||||
public final class Dependencies {
|
||||
|
||||
private final Runtime runtime;
|
||||
private final String cdn;
|
||||
private final String revealjsVersion;
|
||||
private final String bootstrapVersion;
|
||||
private final String jqueryVersion;
|
||||
private final String fontawesomeVersion;
|
||||
private final String octiconsVersion;
|
||||
private final String highlightjsVersion;
|
||||
private final Boolean highlightPluginEnabled;
|
||||
|
||||
@Inject
|
||||
public Dependencies(Runtime runtime) {
|
||||
this.runtime = runtime;
|
||||
this.cdn = runtime.config("gitpitch.dependency.cdn");
|
||||
this.revealjsVersion = runtime.config("gitpitch.dependency.revealjs");
|
||||
this.bootstrapVersion = runtime.config("gitpitch.dependency.bootstrap");
|
||||
this.jqueryVersion = runtime.config("gitpitch.dependency.jquery");
|
||||
this.fontawesomeVersion = runtime.config("gitpitch.dependency.fontawesome");
|
||||
this.octiconsVersion = runtime.config("gitpitch.dependency.octicons");
|
||||
this.highlightjsVersion = runtime.config("gitpitch.dependency.highlightjs");
|
||||
this.highlightPluginEnabled =
|
||||
runtime.configBool("gitpitch.dependency.highlight.plugin", false);
|
||||
}
|
||||
|
||||
public String revealjs(boolean offline, String versionOverride) {
|
||||
return build(offline, REVEALJS, (versionOverride != null) ?
|
||||
versionOverride : revealjsVersion);
|
||||
}
|
||||
|
||||
public String bootstrap(boolean offline) {
|
||||
return build(offline, BOOTSTRAP, bootstrapVersion);
|
||||
}
|
||||
|
||||
public String jquery(boolean offline) {
|
||||
return build(offline, JQUERY, jqueryVersion);
|
||||
}
|
||||
|
||||
public String fontawesome(boolean offline) {
|
||||
return build(offline, FONTAWE, fontawesomeVersion);
|
||||
}
|
||||
|
||||
public String octicons(boolean offline) {
|
||||
return build(offline, OCTICONS, octiconsVersion);
|
||||
}
|
||||
|
||||
public String highlightjs(boolean offline) {
|
||||
return build(offline, HIGHLIGHT, highlightjsVersion);
|
||||
}
|
||||
|
||||
public String gitpitchjs(boolean offline) {
|
||||
return build(offline, GIPITCHJS);
|
||||
}
|
||||
|
||||
public String gitpitchimg(boolean offline) {
|
||||
return build(offline, GIPITCHIMG);
|
||||
}
|
||||
|
||||
public Boolean highlightPluginEnabled() {
|
||||
return highlightPluginEnabled;
|
||||
}
|
||||
|
||||
public Boolean cdnDisabled() {
|
||||
return cdn == null;
|
||||
}
|
||||
|
||||
private String build(boolean offline, String libName) {
|
||||
|
||||
if(offline) {
|
||||
return "./assets" + libName;
|
||||
} else {
|
||||
return (cdn != null) ? (cdn + libName) : (DEFAULT_CDN + libName);
|
||||
}
|
||||
}
|
||||
|
||||
private String build(boolean offline, String libName, String libVersion) {
|
||||
return build(offline, libName) + libVersion;
|
||||
}
|
||||
|
||||
private static final String GIPITCHJS = "/js";
|
||||
private static final String GIPITCHIMG = "/img";
|
||||
private static final String REVEALJS = "/reveal.js/";
|
||||
private static final String BOOTSTRAP = "/bootstrap/";
|
||||
private static final String JQUERY = "/jquery/";
|
||||
private static final String FONTAWE = "/font-awesome/";
|
||||
private static final String OCTICONS = "/octicons/";
|
||||
private static final String HIGHLIGHT = "/highlight.js/";
|
||||
|
||||
private static final String DEFAULT_CDN = "/assets/libs";
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.policies;
|
||||
|
||||
import play.Configuration;
|
||||
import play.Environment;
|
||||
import java.util.List;
|
||||
import javax.inject.*;
|
||||
|
||||
/*
|
||||
* External dependency manager for the GitPitch server.
|
||||
*/
|
||||
@Singleton
|
||||
public final class Runtime {
|
||||
|
||||
private final Configuration cfg;
|
||||
private final Environment env;
|
||||
|
||||
@Inject
|
||||
public Runtime(Configuration cfg,
|
||||
Environment env) {
|
||||
this.cfg = cfg;
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
public String config(String cid) {
|
||||
return cfg.getString(cid);
|
||||
}
|
||||
|
||||
public List configList(String cid) {
|
||||
return cfg.getList(cid);
|
||||
}
|
||||
|
||||
public List configStringList(String cid) {
|
||||
return cfg.getStringList(cid);
|
||||
}
|
||||
|
||||
public boolean configBool(String cid) {
|
||||
return cfg.getBoolean(cid);
|
||||
}
|
||||
|
||||
public boolean configBool(String cid, boolean defaultCfg) {
|
||||
return cfg.getBoolean(cid, defaultCfg);
|
||||
}
|
||||
|
||||
public boolean isProd() {
|
||||
return env.isProd();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.git.GRS;
|
||||
import com.gitpitch.git.GRSService;
|
||||
import com.gitpitch.git.GRSManager;
|
||||
import com.gitpitch.services.DiskService;
|
||||
import com.gitpitch.services.SlideService;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.utils.DelimParams;
|
||||
import com.gitpitch.utils.YAMLOptions;
|
||||
import java.util.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* PITCHME.md code support service.
|
||||
*/
|
||||
@Singleton
|
||||
public class CodeService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final GRSManager grsManager;
|
||||
private final DiskService diskService;
|
||||
private final SlideService slideService;
|
||||
|
||||
@Inject
|
||||
public CodeService(GRSManager grsManager,
|
||||
DiskService diskService,
|
||||
SlideService slideService) {
|
||||
this.grsManager = grsManager;
|
||||
this.diskService = diskService;
|
||||
this.slideService = slideService;
|
||||
}
|
||||
|
||||
public String build(String md,
|
||||
DelimParams dp,
|
||||
PitchParams pp,
|
||||
YAMLOptions yOpts,
|
||||
MarkdownModel mdm) {
|
||||
|
||||
String codeBlock = mdm.extractDelim(md);
|
||||
|
||||
try {
|
||||
|
||||
String codePath = dp.get(MarkdownModel.DELIM_QUERY_CODE);
|
||||
String langHint = dp.get(MarkdownModel.DELIM_QUERY_LANG);
|
||||
String slideTitle = dp.get(MarkdownModel.DELIM_QUERY_TITLE);
|
||||
|
||||
GRS grs = grsManager.get(pp);
|
||||
GRSService grsService = grsManager.getService(grs);
|
||||
|
||||
int downStatus =
|
||||
grsService.download(pp, SOURCE_CODE, codePath);
|
||||
|
||||
String theStructure = slideService.build(md, dp, pp, yOpts, mdm);
|
||||
String theContent = null;
|
||||
|
||||
if(downStatus == 0) {
|
||||
String code = diskService.asText(pp, SOURCE_CODE);
|
||||
if(isMarkdown(codePath, langHint)) {
|
||||
code = prepMarkdown(code);
|
||||
}
|
||||
theContent = buildCodeBlock(mdm.extractDelim(md),
|
||||
code, langHint, slideTitle);
|
||||
} else {
|
||||
theContent = buildCodeBlockError(mdm.extractDelim(md), codePath);
|
||||
}
|
||||
|
||||
return new StringBuffer(theStructure).append(theContent)
|
||||
.toString();
|
||||
|
||||
} catch (Exception ex) {
|
||||
log.warn("build: ex={}", ex);
|
||||
}
|
||||
return codeBlock;
|
||||
}
|
||||
|
||||
private String buildCodeBlock(String delim,
|
||||
String code,
|
||||
String langHint,
|
||||
String slideTitle) {
|
||||
|
||||
StringBuffer slide = new StringBuffer();
|
||||
|
||||
if(slideTitle != null) {
|
||||
slide = slide.append(MarkdownModel.MD_SPACER)
|
||||
.append("<span class='menu-title slide-title'>")
|
||||
.append(slideTitle)
|
||||
.append("</span>")
|
||||
.append(MarkdownModel.MD_SPACER);
|
||||
}
|
||||
|
||||
slide = slide.append(MarkdownModel.MD_CODE_BLOCK_OPEN);
|
||||
|
||||
if(langHint != null) {
|
||||
slide = slide.append(langHint);
|
||||
}
|
||||
|
||||
return slide.append(MarkdownModel.MD_SPACER)
|
||||
.append(code)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.append(MarkdownModel.MD_CODE_BLOCK_CLOSE)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.toString();
|
||||
}
|
||||
|
||||
private String buildCodeBlockError(String delim, String codePath) {
|
||||
return new StringBuffer(SOURCE_CODE_DELIMITER)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.append(codePath)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.append(SOURCE_CODE_NOT_FOUND)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.toString();
|
||||
}
|
||||
|
||||
private boolean isMarkdown(String codePath, String langHint) {
|
||||
return ((codePath != null) && codePath.endsWith(MARKDOWN_EXTENSION)) ||
|
||||
(langHint != null && langHint.toLowerCase().equals("markdown"));
|
||||
}
|
||||
|
||||
/*
|
||||
* To prevent MD code being treated as presentation content
|
||||
* do the following on code-delimiter injection:
|
||||
*
|
||||
* 1. Auto-indent code.
|
||||
* 2. Replace inline code block tripple-ticks with double-ticks
|
||||
* to prevent nested code-block parser and rendering errors.
|
||||
*/
|
||||
private String prepMarkdown(String md) {
|
||||
try {
|
||||
md = Stream.of(lineByLine(md)).map(mdline -> {
|
||||
return mdline.startsWith(MARKDOWN_CODE_TICKS) ?
|
||||
mdline.substring(1) : mdline;
|
||||
}).map(mdline -> {
|
||||
return MARKDOWN_INDENT + mdline;
|
||||
}).collect(Collectors.joining(MarkdownModel.MD_SPACER));
|
||||
} catch(Exception ex) {}
|
||||
return md;
|
||||
}
|
||||
|
||||
private String[] lineByLine(String md) {
|
||||
return md.split("\\r?\\n");
|
||||
}
|
||||
|
||||
private static final String SOURCE_CODE = "PITCHME.code";
|
||||
private static final String SOURCE_CODE_DELIMITER =
|
||||
"### Code Block Delimiter";
|
||||
private static final String SOURCE_CODE_NOT_FOUND =
|
||||
"### Source File Not Found";
|
||||
private static final String MARKDOWN_EXTENSION = ".md";
|
||||
private static final String MARKDOWN_INDENT = " ";
|
||||
private static final String MARKDOWN_NEWLINE = "\n";
|
||||
private static final String MARKDOWN_CODE_TICKS = "```";
|
||||
}
|
|
@ -1,227 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.git.GRS;
|
||||
import com.gitpitch.git.GRSService;
|
||||
import com.gitpitch.services.WebService;
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import play.Logger;
|
||||
|
||||
import javax.inject.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/*
|
||||
* Composable service supporting Markdown includes in
|
||||
* the form of:
|
||||
*
|
||||
* ---?include=/path/to/some.md
|
||||
* +++?include=/path/to/other.md
|
||||
*/
|
||||
@Singleton
|
||||
public class ComposableService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final DiskService ds;
|
||||
private final WebService ws;
|
||||
|
||||
@Inject
|
||||
public ComposableService(DiskService ds,
|
||||
WebService ws) {
|
||||
|
||||
this.ds = ds;
|
||||
this.ws = ws;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make best effort to process composable presentation
|
||||
* includes within PITCHME.md.
|
||||
*/
|
||||
public void compose(PitchParams pp,
|
||||
GRS grs,
|
||||
GRSService grsService) {
|
||||
|
||||
try {
|
||||
|
||||
Path mdPath = ds.asPath(pp, PitchParams.PITCHME_MD);
|
||||
|
||||
String composed = null;
|
||||
try (Stream<String> stream = Files.lines(mdPath)) {
|
||||
|
||||
composed = stream.map(md -> {
|
||||
|
||||
if(md.startsWith(HSLIDE_INCLUDE)) {
|
||||
|
||||
String included = handleInclude(pp,
|
||||
md,
|
||||
HSLIDE_INCLUDE,
|
||||
grsService,
|
||||
grs.getHeaders());
|
||||
if(included != null) {
|
||||
return MarkdownModel.HSLIDE_DELIM_DEFAULT +
|
||||
NEWLINES + included;
|
||||
} else {
|
||||
return notFound(MarkdownModel.HSLIDE_DELIM_DEFAULT,
|
||||
includePath(md, HSLIDE_INCLUDE));
|
||||
}
|
||||
} else
|
||||
if(md.startsWith(VSLIDE_INCLUDE)) {
|
||||
|
||||
String included = handleInclude(pp,
|
||||
md,
|
||||
VSLIDE_INCLUDE,
|
||||
grsService,
|
||||
grs.getHeaders());
|
||||
if(included != null) {
|
||||
return MarkdownModel.VSLIDE_DELIM_DEFAULT +
|
||||
NEWLINES + included;
|
||||
} else {
|
||||
return notFound(MarkdownModel.VSLIDE_DELIM_DEFAULT,
|
||||
includePath(md, VSLIDE_INCLUDE));
|
||||
}
|
||||
} else {
|
||||
return md;
|
||||
}
|
||||
}).collect(Collectors.joining("\n"));
|
||||
|
||||
boolean overwritten = overwrite(pp, mdPath, composed);
|
||||
log.debug("compose: overwritten md={}", overwritten);
|
||||
|
||||
} catch (Exception mex) {
|
||||
log.warn("Markdown processing ex={}", mex);
|
||||
composed = "PITCHME.md could not be parsed.";
|
||||
}
|
||||
|
||||
} catch(Exception stex) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private String handleInclude(PitchParams pp,
|
||||
String md,
|
||||
String includeDelim,
|
||||
GRSService grsService,
|
||||
Map<String,String> headers) {
|
||||
|
||||
String included = null;
|
||||
String includePath = includePath(md, includeDelim);
|
||||
|
||||
if(FORBIDDEN.contains(includePath)) {
|
||||
included = notPermitted(includeDelim, includePath);
|
||||
} else {
|
||||
included = fetchInclude(pp, includePath,
|
||||
includeDelim, grsService, headers);
|
||||
}
|
||||
return included;
|
||||
}
|
||||
|
||||
private String fetchInclude(PitchParams pp,
|
||||
String includePath,
|
||||
String includeDelim,
|
||||
GRSService grsService,
|
||||
Map<String,String> headers) {
|
||||
|
||||
String fetched = null;
|
||||
|
||||
try {
|
||||
|
||||
if(!isAbsolute(includePath))
|
||||
includePath = grsService.raw(pp, includePath, true);
|
||||
|
||||
fetched = ws.fetchText(pp, includePath, headers);
|
||||
|
||||
} catch(Exception fiex) {
|
||||
log.warn("fetchInclude: pp={}, error={}", pp, fiex);
|
||||
}
|
||||
|
||||
return fetched;
|
||||
}
|
||||
|
||||
private String includePath(String md, String includeDelim) {
|
||||
try {
|
||||
return md.substring(includeDelim.length());
|
||||
} catch(Exception ipex) {
|
||||
return md;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean overwrite(PitchParams pp,
|
||||
Path mdPath,
|
||||
String stitched) {
|
||||
try {
|
||||
Files.write(mdPath, stitched.getBytes(),
|
||||
StandardOpenOption.CREATE,
|
||||
StandardOpenOption.TRUNCATE_EXISTING );
|
||||
return true;
|
||||
} catch(Exception fex) {
|
||||
log.warn("overwrite: pp={}, write error={}", pp, fex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private String notFound(String delim, String path) {
|
||||
StringBuffer buf = new StringBuffer(delim);
|
||||
buf.append(NEWLINES)
|
||||
.append("### GitPitch ?Include")
|
||||
.append(NEWLINES).append(".").append(NEWLINES)
|
||||
.append(path)
|
||||
.append(NEWLINES).append(".").append(NEWLINES)
|
||||
.append("Markdown File Not Found");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String notPermitted(String delim, String path) {
|
||||
StringBuffer buf = new StringBuffer(NEWLINES);
|
||||
buf.append("### GitPitch ?Include")
|
||||
.append(NEWLINES).append(".").append(NEWLINES)
|
||||
.append(path)
|
||||
.append(NEWLINES).append(".").append(NEWLINES)
|
||||
.append("Path Not Permitted");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private boolean isAbsolute(String path) {
|
||||
return path.startsWith(HTTP);
|
||||
}
|
||||
|
||||
public final String HSLIDE_INCLUDE =
|
||||
MarkdownModel.HSLIDE_DELIM_DEFAULT + "?include=";
|
||||
public final String VSLIDE_INCLUDE =
|
||||
MarkdownModel.VSLIDE_DELIM_DEFAULT + "?include=";
|
||||
private final String HTTP = "http";
|
||||
private final String NEWLINES = "\n\n";
|
||||
private final List<String> FORBIDDEN =
|
||||
Arrays.asList(PitchParams.PITCHME_MD, "./PITCHME.md");
|
||||
}
|
|
@ -1,288 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.git.GRS;
|
||||
import com.gitpitch.git.GRSService;
|
||||
import com.gitpitch.git.GRSManager;
|
||||
import com.gitpitch.services.WebService;
|
||||
import com.gitpitch.policies.Runtime;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import play.Logger;
|
||||
|
||||
import javax.inject.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Map;
|
||||
|
||||
/*
|
||||
* File system storage service.
|
||||
*/
|
||||
@Singleton
|
||||
public class DiskService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final String storage;
|
||||
private final String decktape;
|
||||
private final ShellService shellService;
|
||||
private final Runtime runtime;
|
||||
private final WebService ws;
|
||||
|
||||
@Inject
|
||||
public DiskService(ShellService shellService,
|
||||
Runtime runtime,
|
||||
WebService ws) {
|
||||
|
||||
this.shellService = shellService;
|
||||
this.runtime = runtime;
|
||||
this.ws = ws;
|
||||
this.storage = runtime.config("gitpitch.storage.home");
|
||||
this.decktape = runtime.config("gitpitch.decktape.home");
|
||||
}
|
||||
|
||||
/*
|
||||
* Return PitchParams branch working directory.
|
||||
*/
|
||||
public Path bwd(PitchParams pp) {
|
||||
return Paths.get(storage(), pp.grs, pp.user, pp.repo, pp.branch);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return Path for file within PitchParams branch working directory.
|
||||
*/
|
||||
public Path asPath(PitchParams pp,
|
||||
String filename) {
|
||||
return Paths.get(storage(), pp.grs, pp.user, pp.repo, pp.branch, filename);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return File for file within PitchParams branch working directory.
|
||||
*/
|
||||
public File asFile(PitchParams pp,
|
||||
String filename) {
|
||||
return asPath(pp, filename).toFile();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return text contents for file within PitchParams branch working directory.
|
||||
*/
|
||||
public String asText(PitchParams pp,
|
||||
String filename) {
|
||||
String text = "";
|
||||
try {
|
||||
Path filePath = asPath(pp, filename);
|
||||
text = new String(Files.readAllBytes(filePath));
|
||||
} catch(Exception tex) {}
|
||||
return text;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure PitchParams branch working directory exists.
|
||||
*/
|
||||
public Path ensure(PitchParams pp) {
|
||||
return ensure(bwd(pp));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ensure PitchParams branch working sub-directory exists.
|
||||
*/
|
||||
public Path ensure(PitchParams pp, String subdir) {
|
||||
|
||||
return (subdir != null) ?
|
||||
ensure(asPath(pp, subdir)) : ensure(bwd(pp));
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure PitchParams branch working directory exists.
|
||||
*/
|
||||
public Path ensure(Path dirPath) {
|
||||
|
||||
try {
|
||||
Files.createDirectories(dirPath);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
return dirPath;
|
||||
}
|
||||
|
||||
/*
|
||||
* Download file from source into bwd resulting in dest.
|
||||
*/
|
||||
public int download(PitchParams pp,
|
||||
Path wd,
|
||||
String source,
|
||||
String dest,
|
||||
Map<String,String> headers) {
|
||||
|
||||
int downloaded = 999;
|
||||
|
||||
try {
|
||||
|
||||
log.debug("download: pp={}, source={}", pp, source);
|
||||
|
||||
ensure(bwd(pp));
|
||||
Path destPath = Paths.get(wd.toString(), dest);
|
||||
delete(destPath);
|
||||
|
||||
final long start = System.currentTimeMillis();
|
||||
|
||||
byte[] fetched = ws.fetchBytes(pp, source, headers);
|
||||
|
||||
if (fetched != null) {
|
||||
|
||||
Files.write(destPath, fetched);
|
||||
downloaded = STATUS_OK;
|
||||
log.debug("download: pp={}, time-taken={} (ms) to " +
|
||||
"write {} bytes to {} from source={}", pp,
|
||||
(System.currentTimeMillis() - start),
|
||||
fetched.length, destPath, source);
|
||||
|
||||
} else {
|
||||
log.warn("download: pp={}, failed to download and write " +
|
||||
"from source={}", pp, source);
|
||||
}
|
||||
} catch(Exception dex) {
|
||||
log.warn("download: failed pp={}, from source={}, ex={}",
|
||||
pp, source, dex);
|
||||
}
|
||||
|
||||
return downloaded;
|
||||
}
|
||||
|
||||
public void copyDirectoryFromJar(Path jarPath, String jarDir, Path dest) {
|
||||
|
||||
log.debug("copyDirectoryFromJar: jarPath={}, jarDir={}, dest={}",
|
||||
jarPath, jarDir, dest);
|
||||
|
||||
try(FileSystem fs = FileSystems.newFileSystem(jarPath, null)) {
|
||||
|
||||
final Path source = fs.getPath(jarDir);
|
||||
|
||||
copyDirectory(source, dest);
|
||||
|
||||
} catch(Exception cex) {
|
||||
log.warn("copyDirectoryFromJar: jarPath={}, jarDir={}, dest={}, ex={}",
|
||||
jarPath, jarDir, dest, cex);
|
||||
}
|
||||
}
|
||||
|
||||
public void copyDirectory(Path source, Path dest) {
|
||||
|
||||
log.debug("copyDirectory: source={}, dest={}", source, dest);
|
||||
|
||||
try {
|
||||
|
||||
Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
|
||||
|
||||
public FileVisitResult preVisitDirectory(Path dir,
|
||||
BasicFileAttributes attrs) throws IOException {
|
||||
|
||||
Path relative = source.relativize(dir);
|
||||
Path visitPath =
|
||||
Paths.get(dest.toString(), relative.toString());
|
||||
ensure(visitPath);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file,
|
||||
BasicFileAttributes attrs) throws IOException {
|
||||
|
||||
Path copyTarget = Paths.get(dest.toString(),
|
||||
source.relativize(file).toString());
|
||||
if(!file.getFileName().toString().matches("\\..*") &&
|
||||
!copyTarget.getFileName().toString().matches("\\..*")) {
|
||||
Files.copy(file, copyTarget);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
|
||||
} catch(Exception cex) {
|
||||
log.warn("copyDirectory: source={}, dest={}, ex={}", source, dest, cex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete file within PitchParams working directory.
|
||||
*/
|
||||
public void delete(PitchParams pp,
|
||||
String filename) {
|
||||
|
||||
delete(asPath(pp, filename));
|
||||
}
|
||||
|
||||
/*
|
||||
* Recursively delete a target directory and contents.
|
||||
*/
|
||||
public void deepDelete(PitchParams pp, String target) {
|
||||
Path branchPath = asPath(pp, target);
|
||||
deepDelete(branchPath.toFile());
|
||||
}
|
||||
|
||||
/*
|
||||
* Recursively delete a target directory and contents.
|
||||
*/
|
||||
public void deepDelete(File directory) {
|
||||
|
||||
try {
|
||||
if(directory.exists()) {
|
||||
FileUtils.deleteDirectory(directory);
|
||||
}
|
||||
} catch (IOException ioex) {
|
||||
log.warn("deepDelete: {}, ex={}", directory, ioex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete file within PitchParams working directory.
|
||||
*/
|
||||
public void delete(Path filePath) {
|
||||
|
||||
try {
|
||||
Files.deleteIfExists(filePath);
|
||||
} catch (Exception dex) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return disk storage home directory.
|
||||
*/
|
||||
public String storage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return DeckTape PDF Exporter home directory.
|
||||
*/
|
||||
public String decktape() {
|
||||
return decktape;
|
||||
}
|
||||
|
||||
private static final Integer STATUS_OK = 0;
|
||||
}
|
|
@ -1,241 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.services.DiskService;
|
||||
import com.gitpitch.services.SlideService;
|
||||
import com.gitpitch.git.GRS;
|
||||
import com.gitpitch.git.GRSService;
|
||||
import com.gitpitch.git.GRSManager;
|
||||
import com.gitpitch.git.vendors.GitHub;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.utils.DelimParams;
|
||||
import com.gitpitch.utils.YAMLOptions;
|
||||
import java.util.*;
|
||||
import java.nio.file.*;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* PITCHME.md GIST support service.
|
||||
*/
|
||||
@Singleton
|
||||
public class GISTService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final GRSManager grsManager;
|
||||
private final DiskService diskService;
|
||||
private final SlideService slideService;
|
||||
|
||||
@Inject
|
||||
public GISTService(GRSManager grsManager,
|
||||
DiskService diskService,
|
||||
SlideService slideService) {
|
||||
this.grsManager = grsManager;
|
||||
this.diskService = diskService;
|
||||
this.slideService = slideService;
|
||||
}
|
||||
|
||||
public String build(String md,
|
||||
DelimParams dp,
|
||||
PitchParams pp,
|
||||
YAMLOptions yOpts,
|
||||
MarkdownModel mdm) {
|
||||
|
||||
try {
|
||||
|
||||
String gid = dp.get(MarkdownModel.DELIM_QUERY_GIST);
|
||||
|
||||
if(backCompat(gid)) {
|
||||
|
||||
return buildBackCompat(md, dp, pp, yOpts, mdm);
|
||||
|
||||
} else {
|
||||
|
||||
String fileHint = dp.get(MarkdownModel.DELIM_QUERY_FILE);
|
||||
String langHint = dp.get(MarkdownModel.DELIM_QUERY_LANG);
|
||||
String slideTitle = dp.get(MarkdownModel.DELIM_QUERY_TITLE);
|
||||
String extractedDelim = mdm.extractDelim(md);
|
||||
|
||||
/*
|
||||
* GIST is a GitHub specific service so override
|
||||
* active-GRS to ensure communiction with GitHub.
|
||||
*/
|
||||
GRS grs = grsManager.get(GitHub.TYPE);
|
||||
GRSService grsService = grsManager.getService(grs);
|
||||
Path branchPath = diskService.ensure(pp);
|
||||
String gistLink = grsService.gist(pp, gid, fileHint);
|
||||
|
||||
int downStatus =
|
||||
diskService.download(pp, branchPath, gistLink,
|
||||
GIST_CODE, grs.getHeaders());
|
||||
|
||||
String theStructure = slideService.build(md, dp, pp, yOpts, mdm);
|
||||
String theContent = null;
|
||||
if(downStatus == 0) {
|
||||
String code = diskService.asText(pp, GIST_CODE);
|
||||
theContent = buildCodeBlock(extractedDelim,
|
||||
code, langHint, slideTitle);
|
||||
} else {
|
||||
theContent =
|
||||
buildCodeBlockError(extractedDelim, gid, fileHint);
|
||||
}
|
||||
|
||||
return new StringBuffer(theStructure).append(theContent)
|
||||
.toString();
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
log.warn("build: ex={}", ex);
|
||||
return slideService.build(md, dp, pp, yOpts, mdm);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String offline() {
|
||||
return new StringBuffer(OFFLINE_GIST).append(MarkdownModel.MD_SPACER)
|
||||
.append(OFFLINE_NOTICE)
|
||||
.toString();
|
||||
}
|
||||
|
||||
private String buildCodeBlock(String delim,
|
||||
String code,
|
||||
String langHint,
|
||||
String slideTitle) {
|
||||
|
||||
log.debug("buildCodeBlock: delim={}, langHint={}, slideTitle={}",
|
||||
delim, langHint, slideTitle);
|
||||
|
||||
StringBuffer slide = new StringBuffer();
|
||||
|
||||
if(slideTitle != null) {
|
||||
|
||||
slide = slide.append(MarkdownModel.MD_SPACER)
|
||||
.append("<span class='menu-title slide-title'>")
|
||||
.append(slideTitle)
|
||||
.append("</span>")
|
||||
.append(MarkdownModel.MD_SPACER);
|
||||
}
|
||||
|
||||
slide = slide.append(MarkdownModel.MD_CODE_BLOCK_OPEN);
|
||||
|
||||
if(langHint != null) {
|
||||
slide = slide.append(langHint);
|
||||
}
|
||||
|
||||
return slide.append(MarkdownModel.MD_SPACER)
|
||||
.append(code)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.append(MarkdownModel.MD_CODE_BLOCK_CLOSE)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.toString();
|
||||
}
|
||||
|
||||
private String buildCodeBlockError(String delim,
|
||||
String codePath,
|
||||
String fileHint) {
|
||||
|
||||
log.debug("buildCodeBlockError: delim={}, codePath={}, fileHint={}",
|
||||
delim, codePath, fileHint);
|
||||
|
||||
String filePath = fileHint != null ? fileHint : GIST_DEFAULT_FILE;
|
||||
filePath = "[ " + filePath + " ]";
|
||||
return new StringBuffer(GIST_DELIMITER)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.append(codePath)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.append(filePath)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.append(GIST_NOT_FOUND)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.toString();
|
||||
}
|
||||
|
||||
private boolean backCompat(String gid) {
|
||||
return !gid.contains(GIST_ID_DELIM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide backward compatible support for embedding
|
||||
* GIST within an iframe. This approach has been superceded
|
||||
* by injecting GIST source into code-blocks.
|
||||
*/
|
||||
private String buildBackCompat(String md,
|
||||
DelimParams dp,
|
||||
PitchParams pp,
|
||||
YAMLOptions yOpts,
|
||||
MarkdownModel mdm) {
|
||||
|
||||
try {
|
||||
|
||||
String gid = dp.get(MarkdownModel.DELIM_QUERY_GIST);
|
||||
|
||||
String gistCallback =
|
||||
com.gitpitch.controllers.routes.PitchController.gist(gid)
|
||||
.url();
|
||||
|
||||
String theStructure = slideService.build(md, dp, pp, yOpts, mdm);
|
||||
return new StringBuffer(theStructure)
|
||||
.append(GIST_DIV_OPEN)
|
||||
.append(GIST_DIV_CLASS)
|
||||
.append(GIST_IFR_OPEN)
|
||||
.append(gistCallback)
|
||||
.append(GIST_IFR_CLSE)
|
||||
.append(GIST_DIV_CLSE)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.toString();
|
||||
|
||||
} catch (Exception ex) {
|
||||
log.warn("buildBackCompat: ex={}", ex);
|
||||
return slideService.build(md, dp, pp, yOpts, mdm);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final String GIST_CODE = "PITCHME.gist";
|
||||
private static final String GIST_DELIMITER = "### GIST Delimiter";
|
||||
private static final String GIST_NOT_FOUND = "### GIST Not Found";
|
||||
private static final String GIST_ID_DELIM = "/";
|
||||
private static final String GIST_DEFAULT_FILE = "Default File";
|
||||
|
||||
/*
|
||||
* BackCompat GIST IFrame Frags (scrolling permitted).
|
||||
*/
|
||||
private static final String GIST_DIV_OPEN = "<div data-gist=\"true\" ";
|
||||
private static final String GIST_DIV_CLASS = "class=\"stretch\">";
|
||||
private static final String GIST_IFR_OPEN =
|
||||
"<iframe width=\"100%\" height=\"100%\" src=\"";
|
||||
private static final String GIST_IFR_CLSE =
|
||||
"\" frameborder=\"0\" scrolling=\"yes\" allowfullscreen></iframe>";
|
||||
private static final String GIST_DIV_CLSE = "</div>";
|
||||
/*
|
||||
* BackCompat Offline GIST Frags.
|
||||
*/
|
||||
private static final String OFFLINE_GIST = "#### GIST Slide Disabled";
|
||||
private static final String OFFLINE_NOTICE = "#### [ GitPitch Offline ]";
|
||||
|
||||
}
|
|
@ -1,435 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.gitpitch.factory.MarkdownModelFactory;
|
||||
import com.gitpitch.git.*;
|
||||
import com.gitpitch.models.GitRepoModel;
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.models.SlideshowModel;
|
||||
import com.gitpitch.policies.CacheTimeout;
|
||||
import com.gitpitch.executors.BackEndThreads;
|
||||
import com.gitpitch.utils.*;
|
||||
import play.Logger;
|
||||
import play.cache.*;
|
||||
import play.libs.ws.*;
|
||||
|
||||
import javax.inject.*;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/*
|
||||
* GitHub API integration service.
|
||||
*/
|
||||
@Singleton
|
||||
public class GitService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final ConcurrentHashMap<String, CountDownLatch> repoLatchMap =
|
||||
new ConcurrentHashMap();
|
||||
private final ConcurrentHashMap<String, CountDownLatch> yamlLatchMap =
|
||||
new ConcurrentHashMap();
|
||||
private final ConcurrentHashMap<String, CountDownLatch> markdownLatchMap =
|
||||
new ConcurrentHashMap();
|
||||
|
||||
private final GRSManager grsManager;
|
||||
private final DiskService diskService;
|
||||
private final PrintService printService;
|
||||
private final ShellService shellService;
|
||||
private final CacheTimeout cacheTimeout;
|
||||
private final BackEndThreads backEndThreads;
|
||||
private final MarkdownModelFactory markdownModelFactory;
|
||||
private final ComposableService composableService;
|
||||
private final WSClient wsClient;
|
||||
private final CacheApi pitchCache;
|
||||
|
||||
@Inject
|
||||
public GitService(GRSManager grsManager,
|
||||
DiskService diskService,
|
||||
PrintService printService,
|
||||
ShellService shellService,
|
||||
CacheTimeout cacheTimeout,
|
||||
BackEndThreads backEndThreads,
|
||||
MarkdownModelFactory markdownModelFactory,
|
||||
ComposableService composableService,
|
||||
WSClient wsClient,
|
||||
CacheApi pitchCache) {
|
||||
|
||||
this.grsManager = grsManager;
|
||||
this.diskService = diskService;
|
||||
this.printService = printService;
|
||||
this.shellService = shellService;
|
||||
this.cacheTimeout = cacheTimeout;
|
||||
this.backEndThreads = backEndThreads;
|
||||
this.markdownModelFactory = markdownModelFactory;
|
||||
this.composableService = composableService;
|
||||
this.wsClient = wsClient;
|
||||
this.pitchCache = pitchCache;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch GitHub repo meta-data on GitHub API.
|
||||
*/
|
||||
public CountDownLatch fetchRepo(PitchParams pp) {
|
||||
|
||||
final String grmKey = GitRepoModel.genKey(pp);
|
||||
log.debug("fetchRepo: pp={}", pp);
|
||||
CountDownLatch freshLatch = new CountDownLatch(1);
|
||||
CountDownLatch activeLatch =
|
||||
repoLatchMap.putIfAbsent(grmKey, freshLatch);
|
||||
|
||||
if (activeLatch != null) {
|
||||
|
||||
/*
|
||||
* Non-null activeLatch implies a fetchRepo() operation
|
||||
* is already in progress for this /{user}/{repo}. So
|
||||
* activeLatch so caller can block until operation completes.
|
||||
*/
|
||||
log.debug("fetchRepo: pp={}, already in progress, " +
|
||||
"returning existing activeLatch={}", pp, activeLatch);
|
||||
return activeLatch;
|
||||
|
||||
} else {
|
||||
|
||||
GRS grs = grsManager.get(pp);
|
||||
final GRSService grsService = grsManager.getService(grs);
|
||||
String apiCall = grsService.repo(pp);
|
||||
|
||||
log.debug("fetchRepo: apiCall={}", apiCall);
|
||||
final long start = System.currentTimeMillis();
|
||||
|
||||
WSRequest apiRequest = wsClient.url(apiCall);
|
||||
|
||||
grs.getHeaders().forEach((k,v) -> {
|
||||
apiRequest.setHeader(k, v);
|
||||
});
|
||||
|
||||
CompletableFuture<WSResponse> apiFuture =
|
||||
apiRequest.get().toCompletableFuture();
|
||||
|
||||
CompletableFuture<GitRepoModel> rmFuture =
|
||||
apiFuture.thenApplyAsync(apiResp -> {
|
||||
|
||||
log.debug("fetchRepo: pp={}, fetch meta time-taken={}",
|
||||
pp, (System.currentTimeMillis() - start));
|
||||
|
||||
log.info("{}: API Rate Limit Status [ {}, {} ]",
|
||||
grs.getName(),
|
||||
apiResp.getHeader(API_RATE_LIMIT),
|
||||
apiResp.getHeader(API_RATE_LIMIT_REMAINING));
|
||||
|
||||
try {
|
||||
|
||||
if (apiResp.getStatus() == HTTP_OK) {
|
||||
|
||||
try {
|
||||
|
||||
JsonNode json = apiResp.asJson();
|
||||
GitRepoModel grm = grsService.model(pp, json);
|
||||
|
||||
/*
|
||||
* Update pitchCache with new GitRepoModel
|
||||
* generated using GitHub API response data.
|
||||
*/
|
||||
pitchCache.set(grm.key(), grm, cacheTimeout.grm(pp));
|
||||
|
||||
} catch (Exception ex) {
|
||||
/*
|
||||
* Prevent any runtime errors, such as JSON parsing,
|
||||
* from propogating to the front end.
|
||||
*/
|
||||
log.warn("fetchRepo: pp={}, unexpected ex={}", pp, ex);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
log.debug("fetchRepo: pp={}, fail status={}",
|
||||
pp, apiResp.getStatus());
|
||||
|
||||
try {
|
||||
|
||||
String remainingHdr =
|
||||
apiResp.getHeader(API_RATE_LIMIT_REMAINING);
|
||||
int rateLimitRemaining =
|
||||
Integer.parseInt(remainingHdr);
|
||||
|
||||
if (rateLimitRemaining <= 0) {
|
||||
log.warn("WARNING! {} API rate limit exceeded.", grs.getName());
|
||||
}
|
||||
|
||||
} catch (Exception rlex) {
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception rex) {
|
||||
log.warn("fetchRepo: pp={}, unexpected runtime ex={}", pp, rex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Current operation completed, so remove latch associated
|
||||
* with operation from repoLatchMap to permit future operations
|
||||
* on this /{user}/{repo}.
|
||||
*/
|
||||
releaseCountDownLatch(repoLatchMap, grmKey);
|
||||
|
||||
/*
|
||||
* Operation completed, valid result cached, no return required.
|
||||
*/
|
||||
return null;
|
||||
|
||||
}, backEndThreads.POOL)
|
||||
.handle((result, error) -> {
|
||||
|
||||
if (error != null) {
|
||||
|
||||
log.warn("fetchRepo: pp={}, fetch error={}", pp, error);
|
||||
releaseCountDownLatch(repoLatchMap, grmKey);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
return freshLatch;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch PITCHME.yaml configuration from GitHub repo.
|
||||
*/
|
||||
public CountDownLatch fetchYAML(PitchParams pp) {
|
||||
|
||||
final String ssmKey = SlideshowModel.genKey(pp);
|
||||
|
||||
CountDownLatch freshLatch = new CountDownLatch(1);
|
||||
CountDownLatch activeLatch =
|
||||
yamlLatchMap.putIfAbsent(ssmKey, freshLatch);
|
||||
|
||||
if (activeLatch != null) {
|
||||
/*
|
||||
* A non-null activeLatch implies a fetchYAML()
|
||||
* operation is already in progress for the current
|
||||
* /{user}/{repo}?b={branch}.
|
||||
*/
|
||||
log.debug("fetchYAML: pp={}, already in progress, " +
|
||||
"returning existing activeLatch={}", pp, activeLatch);
|
||||
return activeLatch;
|
||||
|
||||
} else {
|
||||
|
||||
CompletableFuture<Void> syncFuture =
|
||||
CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
GRS grs = grsManager.get(pp);
|
||||
GRSService grsService = grsManager.getService(grs);
|
||||
int downYAML = grsService.download(pp,
|
||||
PitchParams.PITCHME_YAML, pp.YAML());
|
||||
boolean downOk = downYAML == STATUS_OK;
|
||||
log.debug("fetchYAML: pp={}, colocated YAML={}",
|
||||
pp, downYAML);
|
||||
|
||||
/*
|
||||
* If PITCHME.yaml not found at pp.pitchme path
|
||||
* try locate file using GitPitch convention
|
||||
* default by looking in repo root directory.
|
||||
*/
|
||||
if(!downOk && pp.pitchme != null) {
|
||||
downYAML =
|
||||
grsService.download(pp,
|
||||
PitchParams.PITCHME_YAML,
|
||||
PitchParams.PITCHME_YAML);
|
||||
downOk = downYAML == STATUS_OK;
|
||||
log.debug("fetchYAML: pp={}, fallback YAML={}",
|
||||
pp, downYAML);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update pitchCache with new SlideshowModel.
|
||||
*/
|
||||
SlideshowModel ssm =
|
||||
SlideshowModel.build(pp, downOk, grsService, diskService);
|
||||
pitchCache.set(ssm.key(), ssm, cacheTimeout.ssm(pp));
|
||||
|
||||
/*
|
||||
* Current operation completed, so remove latch associated
|
||||
* with operation from yamlLatchMap to permit future
|
||||
* operations on this /{user}/{repo}?b={branch}.
|
||||
*/
|
||||
releaseCountDownLatch(yamlLatchMap, ssmKey);
|
||||
|
||||
/*
|
||||
* Operation completed, valid result cached, no return required.
|
||||
*/
|
||||
return null;
|
||||
|
||||
}, backEndThreads.POOL)
|
||||
.handle((result, error) -> {
|
||||
|
||||
if (error != null) {
|
||||
|
||||
log.warn("fetchYAML: pp={}, fetch error={}", pp, error);
|
||||
releaseCountDownLatch(yamlLatchMap, ssmKey);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
return freshLatch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch PITCHME.md markdown from GitHub repo.
|
||||
*/
|
||||
public CountDownLatch fetchMarkdown(PitchParams pp) {
|
||||
|
||||
final String mdmKey = MarkdownModel.genKey(pp);
|
||||
|
||||
CountDownLatch freshLatch = new CountDownLatch(1);
|
||||
CountDownLatch activeLatch =
|
||||
markdownLatchMap.putIfAbsent(mdmKey, freshLatch);
|
||||
|
||||
if (activeLatch != null) {
|
||||
/*
|
||||
* A non-null activeLatch implies a fetchMarkdown()
|
||||
* operation is already in progress for the current
|
||||
* /{user}/{repo}?b={branch}.
|
||||
*/
|
||||
log.debug("fetchMarkdown: pp={}, already in progress, " +
|
||||
"returning existing activeLatch={}", pp, activeLatch);
|
||||
return activeLatch;
|
||||
|
||||
} else {
|
||||
|
||||
CompletableFuture<Void> syncFuture =
|
||||
CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
GRS grs = grsManager.get(pp);
|
||||
GRSService grsService = grsManager.getService(grs);
|
||||
|
||||
int downStatus = grsService.download(pp,
|
||||
PitchParams.PITCHME_MD, pp.MD());
|
||||
|
||||
if (downStatus == STATUS_OK) {
|
||||
|
||||
/*
|
||||
* Process Composable Presentation includes
|
||||
* found within PITCHME.md.
|
||||
*/
|
||||
composableService.compose(pp, grs, grsService);
|
||||
|
||||
String ssmKey = SlideshowModel.genKey(pp);
|
||||
Optional<SlideshowModel> ssmo =
|
||||
Optional.ofNullable(pitchCache.get(ssmKey));
|
||||
|
||||
/*
|
||||
* The SSM in the pitchCache can be absent if
|
||||
* we are currently processing a print or offline
|
||||
* download. In these caes, quickly reconstitute
|
||||
* the SSM using YAML on disk so markdown rendering
|
||||
* can honor all custom YAML configurations.
|
||||
*/
|
||||
if(!ssmo.isPresent()) {
|
||||
|
||||
SlideshowModel ssm =
|
||||
SlideshowModel.build(pp, true, grsService, diskService);
|
||||
ssmo = Optional.of(ssm);
|
||||
}
|
||||
|
||||
MarkdownRenderer mrndr = MarkdownRenderer.build(pp,
|
||||
ssmo, grsService, diskService);
|
||||
|
||||
// MarkdownModel mdm = MarkdownModel.consume(mrndr);
|
||||
MarkdownModel mdm =
|
||||
(MarkdownModel) markdownModelFactory.create(mrndr);
|
||||
pitchCache.set(mdmKey, mdm, cacheTimeout.mdm(pp));
|
||||
|
||||
} else {
|
||||
log.debug("fetchMarkdown: pp={}, failed status={}",
|
||||
pp, downStatus);
|
||||
}
|
||||
|
||||
/*
|
||||
* Current operation completed, so remove latch associated
|
||||
* with operation from markdownLatchMap to permit future
|
||||
* operations on this /{user}/{repo}?b={branch}.
|
||||
*/
|
||||
releaseCountDownLatch(markdownLatchMap, mdmKey);
|
||||
|
||||
/*
|
||||
* Operation completed, valid result cached, no return required.
|
||||
*/
|
||||
return null;
|
||||
|
||||
}, backEndThreads.POOL)
|
||||
.handle((result, error) -> {
|
||||
|
||||
if (error != null) {
|
||||
|
||||
log.warn("fetchMarkdown: pp={}, fetch error={}",
|
||||
pp, error);
|
||||
releaseCountDownLatch(markdownLatchMap, mdmKey);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
return freshLatch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Call when fetchXXX operation has completed either
|
||||
* successfully or on error. Remove latch associated with
|
||||
* operation from xxxLatchMap to permit future operations
|
||||
* on /{user}/{repo}/{branch} associated with latchKey.
|
||||
*/
|
||||
private void releaseCountDownLatch(ConcurrentHashMap<String,
|
||||
CountDownLatch> latchMap,
|
||||
String latchKey) {
|
||||
|
||||
CountDownLatch completedLatch = latchMap.remove(latchKey);
|
||||
|
||||
if (completedLatch != null) {
|
||||
completedLatch.countDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final String GHUB_REPO_META =
|
||||
"https://api.github.com/repos/";
|
||||
private static final String GIT_MASTER = "master";
|
||||
private static final String SLASH = "/";
|
||||
private static final int HTTP_OK = 200;
|
||||
private static final int STATUS_OK = 0;
|
||||
private static final String API_HEADER_AUTH = "Authorization";
|
||||
private static final String API_HEADER_TOKEN = "token ";
|
||||
private static final String API_RATE_LIMIT = "X-RateLimit-Limit";
|
||||
private static final String API_RATE_LIMIT_REMAINING = "X-RateLimit-Remaining";
|
||||
}
|
|
@ -1,177 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.utils.DelimParams;
|
||||
import com.gitpitch.utils.YAMLOptions;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import java.util.*;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* PITCHME.md image support service.
|
||||
*/
|
||||
@Singleton
|
||||
public class ImageService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
public String buildBackground(PitchParams pp,
|
||||
YAMLOptions yOpts) {
|
||||
|
||||
return buildBackground(yOpts.fetchImageBg(pp),
|
||||
yOpts.fetchImageBgSize(pp),
|
||||
yOpts.fetchImageBgColor(pp),
|
||||
yOpts.fetchImageBgPosition(pp),
|
||||
yOpts.fetchImageBgRepeat(pp),
|
||||
yOpts.fetchTransition(pp));
|
||||
}
|
||||
|
||||
public String buildBackground(String md,
|
||||
DelimParams dp,
|
||||
PitchParams pp,
|
||||
String defaultSize,
|
||||
String defaultColor,
|
||||
String defaultPos,
|
||||
String defaultRepeat,
|
||||
String defaultTransition,
|
||||
MarkdownModel mdm) {
|
||||
|
||||
String bgUrl = dp.get(MarkdownModel.DELIM_QUERY_IMAGE);
|
||||
bgUrl = mdm.linkLive(pp, bgUrl);
|
||||
String bgSize = dp.get(MarkdownModel.DELIM_QUERY_SIZE, defaultSize);
|
||||
String bgColor = dp.get(MarkdownModel.DELIM_QUERY_COLOR, defaultColor);
|
||||
String bgPos = dp.get(MarkdownModel.DELIM_QUERY_POSITION, defaultPos);
|
||||
String bgRepeat =
|
||||
dp.get(MarkdownModel.DELIM_QUERY_REPEAT, defaultRepeat);
|
||||
String bgTransition =
|
||||
dp.get(MarkdownModel.DELIM_QUERY_TRANSITION, defaultTransition);
|
||||
return buildBackground(bgUrl, bgSize, bgColor, bgPos, bgRepeat, bgTransition);
|
||||
}
|
||||
|
||||
private String buildBackground(String bgUrl,
|
||||
String bgSize,
|
||||
String bgColor,
|
||||
String bgPosition,
|
||||
String bgRepeat,
|
||||
String bgTransition) {
|
||||
|
||||
return new StringBuffer(MarkdownModel.MD_SPACER)
|
||||
.append(MarkdownModel.MD_IMAGE_OPEN)
|
||||
.append(bgUrl)
|
||||
.append(MarkdownModel.MD_IMAGE_SIZE)
|
||||
.append(bgSize)
|
||||
.append(MarkdownModel.MD_IMAGE_COLOR)
|
||||
.append(bgColor)
|
||||
.append(MarkdownModel.MD_IMAGE_POSITION)
|
||||
.append(bgPosition)
|
||||
.append(MarkdownModel.MD_IMAGE_REPEAT)
|
||||
.append(bgRepeat)
|
||||
.append(MarkdownModel.MD_IMAGE_TRANSITION)
|
||||
.append(bgTransition)
|
||||
.append(MarkdownModel.MD_CLOSER)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String buildBackgroundOffline(String md) {
|
||||
|
||||
try {
|
||||
|
||||
String frag = md.substring(MarkdownModel.MD_IMAGE_OPEN.length());
|
||||
String fragUrl = frag.substring(0, frag.indexOf("\""));
|
||||
String imageName = FilenameUtils.getName(fragUrl);
|
||||
String imageUrl = IMG_OFFLINE_DIR + imageName;
|
||||
|
||||
return md.replace(fragUrl, imageUrl);
|
||||
} catch (Exception bex) {
|
||||
}
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
public String buildInlineOffline(String imageName) {
|
||||
|
||||
return new StringBuffer(IMG_INLINE_OPEN).append(imageName)
|
||||
.append(IMG_INLINE_CLOSE)
|
||||
.toString();
|
||||
|
||||
}
|
||||
|
||||
public String buildTagOffline(String md) {
|
||||
|
||||
try {
|
||||
|
||||
String imageTagUrl = tagLink(md);
|
||||
String imageTagName = FilenameUtils.getName(imageTagUrl);
|
||||
String offlineTagUrl = IMG_OFFLINE_DIR + imageTagName;
|
||||
return md.replace(imageTagUrl, offlineTagUrl);
|
||||
} catch(Exception tex) {}
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
public boolean inline(String md) {
|
||||
return md.startsWith(MarkdownModel.MD_LINK_OPEN);
|
||||
}
|
||||
|
||||
public boolean background(String md) {
|
||||
return md.contains(MarkdownModel.DATA_IMAGE_ATTR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true is HTML image tag found.
|
||||
*/
|
||||
public boolean tagFound(String md) {
|
||||
return md.startsWith(IMG_TAG_OPEN);
|
||||
}
|
||||
|
||||
public String tagLink(String md) {
|
||||
|
||||
int linkTagStart = md.indexOf(IMG_TAG_SRC_OPEN);
|
||||
int linkStart = linkTagStart + IMG_TAG_SRC_OPEN.length();
|
||||
int linkEnd =
|
||||
md.indexOf(IMG_TAG_SRC_CLOSE, linkStart);
|
||||
|
||||
String tagLink = IMG_TAG_LINK_UNKNOWN;
|
||||
if(linkTagStart != -1 && linkEnd != -1) {
|
||||
tagLink = md.substring(linkStart, linkEnd);
|
||||
}
|
||||
|
||||
return tagLink;
|
||||
}
|
||||
|
||||
private static final String IMG_OFFLINE_DIR = "./assets/md/assets/";
|
||||
private static final String IMG_INLINE_OPEN = "![Image](" + IMG_OFFLINE_DIR;
|
||||
private static final String IMG_INLINE_CLOSE = ")";
|
||||
private static final String IMG_TAG_OPEN = "<img ";
|
||||
private static final String IMG_TAG_SRC_OPEN = "src=\"";
|
||||
private static final String IMG_TAG_SRC_CLOSE = "\"";
|
||||
private static final String IMG_TAG_LINK_UNKNOWN = "#";
|
||||
private static final String IMG_CUSTOM_SIZE_OPTION = "&size=";
|
||||
}
|
|
@ -1,657 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.factory.MarkdownModelFactory;
|
||||
import com.gitpitch.git.*;
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.models.SlideshowModel;
|
||||
import com.gitpitch.executors.BackEndThreads;
|
||||
import com.gitpitch.policies.Runtime;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.utils.YAMLOptions;
|
||||
import com.gitpitch.utils.MarkdownRenderer;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import play.Logger;
|
||||
|
||||
import javax.inject.*;
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/*
|
||||
* PITCHME.zip archive offline service.
|
||||
*/
|
||||
@Singleton
|
||||
public class OfflineService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final GRSManager grsManager;
|
||||
private final DiskService diskService;
|
||||
private final ShellService shellService;
|
||||
private final MarkdownModelFactory markdownModelFactory;
|
||||
private final BackEndThreads backEndThreads;
|
||||
private final Runtime runtime;
|
||||
|
||||
@Inject
|
||||
public OfflineService(GRSManager grsManager,
|
||||
DiskService diskService,
|
||||
ShellService shellService,
|
||||
MarkdownModelFactory markdownModelFactory,
|
||||
BackEndThreads backEndThreads,
|
||||
Runtime runtime) {
|
||||
|
||||
this.grsManager = grsManager;
|
||||
this.diskService = diskService;
|
||||
this.shellService = shellService;
|
||||
this.markdownModelFactory = markdownModelFactory;
|
||||
this.backEndThreads = backEndThreads;
|
||||
this.runtime = runtime;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate and fetch PITCHME.zip.
|
||||
*/
|
||||
public CountDownLatch fetchZip(PitchParams pp,
|
||||
Optional<SlideshowModel> ssmo) {
|
||||
|
||||
log.debug("fetchZip: pp={}, ssmo.isPresent={}",
|
||||
pp, ssmo.isPresent());
|
||||
|
||||
final String zipKey = MarkdownModel.genKey(pp);
|
||||
|
||||
CountDownLatch freshLatch = new CountDownLatch(1);
|
||||
CountDownLatch activeLatch =
|
||||
zipLatchMap.putIfAbsent(zipKey, freshLatch);
|
||||
|
||||
if (activeLatch != null) {
|
||||
/*
|
||||
* A non-null activeLatch implies a fetchZip()
|
||||
* operation is already in progress for the current
|
||||
* /{user}/{repo}?b={branch}.
|
||||
*/
|
||||
log.debug("fetchZip: pp={}, already in progress, " +
|
||||
"returning existing activeLatch={}", pp, activeLatch);
|
||||
return activeLatch;
|
||||
|
||||
} else {
|
||||
|
||||
CompletableFuture<Void> syncFuture =
|
||||
CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
Path branchPath = diskService.ensure(pp);
|
||||
int zipStatus = generateZip(pp, ssmo);
|
||||
|
||||
if (zipStatus != STATUS_OK) {
|
||||
log.warn("fetchZip: pp={}, fetch status={}", pp, zipStatus);
|
||||
}
|
||||
|
||||
/*
|
||||
* Current operation completed, so remove latch associated
|
||||
* with operation from zipLatchMap to permit future
|
||||
* operations on this /{user}/{repo}?b={branch}.
|
||||
*/
|
||||
releaseCountDownLatch(zipLatchMap, zipKey);
|
||||
|
||||
/*
|
||||
* Operation completed, valid result cached, no return required.
|
||||
*/
|
||||
return null;
|
||||
|
||||
}, backEndThreads.POOL)
|
||||
.handle((result, error) -> {
|
||||
|
||||
if (error != null) {
|
||||
|
||||
log.warn("fetchZip: pp={}, fetch error={}", pp, error);
|
||||
releaseCountDownLatch(zipLatchMap, zipKey);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
return freshLatch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Call when fetchXXX operation has completed either
|
||||
* successfully or on error. Remove latch associated with
|
||||
* operation from xxxLatchMap to permit future operations
|
||||
* on /{user}/{repo}?b={branch} associated with latchKey.
|
||||
*/
|
||||
private void releaseCountDownLatch(ConcurrentHashMap<String, CountDownLatch> latchMap,
|
||||
String latchKey) {
|
||||
|
||||
CountDownLatch completedLatch = latchMap.remove(latchKey);
|
||||
|
||||
if (completedLatch != null) {
|
||||
completedLatch.countDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate offline slideshow as self-contained zip archive.
|
||||
*/
|
||||
private int generateZip(PitchParams pp,
|
||||
Optional<SlideshowModel> ssmo) {
|
||||
|
||||
log.debug("generateZip: pp={}, ssmo.isPresent={}",
|
||||
pp, ssmo.isPresent());
|
||||
|
||||
int status = STATUS_UNDEF;
|
||||
|
||||
Path zipRoot = null;
|
||||
|
||||
try {
|
||||
|
||||
zipRoot = prepareZipRoot(pp);
|
||||
|
||||
status = fetchOnlineMarkdown(pp, zipRoot);
|
||||
|
||||
if (status == STATUS_OK)
|
||||
status = processMarkdown(pp, zipRoot, ssmo);
|
||||
|
||||
if (status == STATUS_OK)
|
||||
status = fetchSlideshowHTML(pp, zipRoot);
|
||||
|
||||
if (status == STATUS_OK)
|
||||
status = fetchMenuHTML(pp, zipRoot);
|
||||
|
||||
if (status == STATUS_OK)
|
||||
fetchFixedDependencies(pp, zipRoot);
|
||||
|
||||
if (status == STATUS_OK)
|
||||
fetchYAMLDependencies(pp, zipRoot);
|
||||
|
||||
if (status == STATUS_OK)
|
||||
pruneYAMLDependencies(pp, zipRoot);
|
||||
|
||||
if (status == STATUS_OK)
|
||||
status = buildZip(pp, zipRoot);
|
||||
|
||||
} catch (Exception zex) {
|
||||
log.warn("generateZip: pp={}, ex={}", zex);
|
||||
} finally {
|
||||
|
||||
/*
|
||||
* Clean up artifacts if failed to generate zip.
|
||||
*/
|
||||
if (status != STATUS_OK && zipRoot != null) {
|
||||
diskService.delete(zipRoot.resolve(PITCHME_ZIP));
|
||||
diskService.deepDelete(zipRoot.resolve(ZIP_ROOT_DIR).toFile());
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare zip archive root directory on disk.
|
||||
*/
|
||||
private Path prepareZipRoot(PitchParams pp) {
|
||||
Path zipRoot = diskService.ensure(pp);
|
||||
if(pp.pitchme != null) {
|
||||
zipRoot = zipRoot.resolve(pp.pitchme);
|
||||
}
|
||||
zipRoot = zipRoot.resolve(ZIP_ROOT_DIR);
|
||||
return diskService.ensure(zipRoot);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch online PITCHME.md into ZIP_MD_DIR.
|
||||
*/
|
||||
private int fetchOnlineMarkdown(PitchParams pp, Path zipRoot) {
|
||||
|
||||
String murl =
|
||||
com.gitpitch.controllers.routes.PitchController.markdown(pp.grs,
|
||||
pp.user,
|
||||
pp.repo,
|
||||
pp.branch,
|
||||
pp.pitchme)
|
||||
.absoluteURL(isEncrypted(), hostname());
|
||||
|
||||
Path zipMdPath =
|
||||
diskService.ensure(zipRoot.resolve(ZIP_MD_DIR));
|
||||
return diskService.download(pp,
|
||||
zipMdPath, murl, PITCHME_ONLINE_MD,
|
||||
grsManager.get(pp).getHeaders());
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch Slideshow.html.
|
||||
*/
|
||||
private int fetchSlideshowHTML(PitchParams pp, Path zipRoot) {
|
||||
|
||||
String lurl =
|
||||
com.gitpitch.controllers.routes.PitchController.slideshow(pp.user,
|
||||
pp.repo,
|
||||
pp.branch,
|
||||
pp.grs,
|
||||
pp.theme,
|
||||
pp.pitchme,
|
||||
pp.notes,
|
||||
ENABLED, null, null)
|
||||
.absoluteURL(isEncrypted(), hostname());
|
||||
|
||||
return diskService.download(pp, zipRoot,
|
||||
lurl, INDEX_HTML, grsManager.get(pp).getHeaders());
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch Menu.html.
|
||||
*/
|
||||
private int fetchMenuHTML(PitchParams pp, Path zipRoot) {
|
||||
|
||||
String surl =
|
||||
com.gitpitch.controllers.routes.PitchController.home(pp.grs,
|
||||
pp.user,
|
||||
pp.repo,
|
||||
pp.branch,
|
||||
pp.theme,
|
||||
pp.pitchme,
|
||||
ENABLED)
|
||||
.absoluteURL(isEncrypted(), hostname());
|
||||
|
||||
return diskService.download(pp, zipRoot,
|
||||
surl, MENU_HTML, grsManager.get(pp).getHeaders());
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch fixed JS and CSS dependencies for GitPitch slideshow.
|
||||
*/
|
||||
private void fetchFixedDependencies(PitchParams pp, Path zipRoot)
|
||||
throws java.io.IOException {
|
||||
|
||||
Path destPath =
|
||||
diskService.ensure(zipRoot.resolve(ZIP_ASSETS_DIR));
|
||||
|
||||
if(runtime.isProd()) {
|
||||
|
||||
Path jarPath = prodModeDependenciesJar();
|
||||
if(jarPath.toFile().exists()) {
|
||||
diskService.copyDirectoryFromJar(jarPath,
|
||||
FIXED_ASSETS, destPath);
|
||||
} else {
|
||||
log.warn("fetchFixedDependencies: [ prod ] jar " +
|
||||
"not found={}", jarPath);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
Path fixedAssetsPath = devModeFixedDependencies();
|
||||
if (fixedAssetsPath.toFile().exists()) {
|
||||
diskService.copyDirectory(fixedAssetsPath, destPath);
|
||||
} else {
|
||||
log.debug("fetchFixedDependencies: [ dev ] fixed assets " +
|
||||
"not found={}", fixedAssetsPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert online PITCHME.md to offline PITCHME.md.
|
||||
*/
|
||||
private int processMarkdown(PitchParams pp,
|
||||
Path zipRoot,
|
||||
Optional<SlideshowModel> ssmo) {
|
||||
|
||||
int status = STATUS_UNDEF;
|
||||
|
||||
String consumed = null;
|
||||
Path mdOnlinePath = zipRoot.resolve(PITCHME_ONLINE_PATH);
|
||||
File mdOnlineFile = mdOnlinePath.toFile();
|
||||
|
||||
if (mdOnlineFile.exists()) {
|
||||
|
||||
GRSService grsService =
|
||||
grsManager.getService(grsManager.get(pp));
|
||||
|
||||
MarkdownRenderer mrndr =
|
||||
MarkdownRenderer.build(pp, ssmo, grsService, diskService);
|
||||
|
||||
MarkdownModel markdownModel =
|
||||
(MarkdownModel) markdownModelFactory.create(mrndr);
|
||||
|
||||
try (Stream<String> stream = Files.lines(mdOnlinePath)) {
|
||||
|
||||
consumed = stream.map(md -> {
|
||||
return markdownModel.offline(md);
|
||||
}).collect(Collectors.joining("\n"));
|
||||
|
||||
Path mdOfflinePath =
|
||||
zipRoot.resolve(PITCHME_OFFLINE_PATH);
|
||||
Files.write(mdOfflinePath, consumed.getBytes());
|
||||
|
||||
fetchOnlineAssets(pp, zipRoot);
|
||||
|
||||
status = STATUS_OK;
|
||||
|
||||
} catch (Exception mex) {
|
||||
log.warn("processMarkdown: ex={}", mex);
|
||||
}
|
||||
|
||||
} else {
|
||||
log.warn("processMarkdown: mdOnline not found={}", mdOnlineFile);
|
||||
}
|
||||
|
||||
log.debug("processMarkdown: returning status={}", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch online PITCHME.md image assets into ZIP_MD_ASSETS_DIR.
|
||||
*/
|
||||
private void fetchOnlineAssets(PitchParams pp, Path zipRoot) {
|
||||
|
||||
List<String> assetUrls = null;
|
||||
|
||||
Path mdOnlinePath = zipRoot.resolve(PITCHME_ONLINE_PATH);
|
||||
File mdOnlineFile = mdOnlinePath.toFile();
|
||||
|
||||
if (mdOnlineFile.exists()) {
|
||||
|
||||
MarkdownModel markdownModel =
|
||||
(MarkdownModel) markdownModelFactory.create(null);
|
||||
|
||||
try (Stream<String> stream = Files.lines(mdOnlinePath)) {
|
||||
|
||||
assetUrls = stream.map(md -> {
|
||||
return markdownModel.offlineAssets(md);
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
log.debug("fetchOnlineAssets: assetUrls={}", assetUrls);
|
||||
|
||||
Path zipMdAssetsPath = zipRoot.resolve(ZIP_MD_ASSETS_DIR);
|
||||
zipMdAssetsPath = diskService.ensure(zipMdAssetsPath);
|
||||
|
||||
List<String> fetched = new ArrayList<String>();
|
||||
|
||||
for (String assetUrl : assetUrls) {
|
||||
if (assetUrl != null &&
|
||||
!fetched.contains(assetUrl)) {
|
||||
diskService.download(pp, zipMdAssetsPath, assetUrl,
|
||||
FilenameUtils.getName(assetUrl),
|
||||
grsManager.get(pp).getHeaders());
|
||||
fetched.add(assetUrl);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception mex) {
|
||||
log.warn("fetchOnlineAssets: ex={}", mex);
|
||||
}
|
||||
|
||||
} else {
|
||||
log.warn("fetchOnlineAssets: mdOnline not found={}", mdOnlineFile);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch PITCHME.yaml dependencies into zip archive.
|
||||
*/
|
||||
private void fetchYAMLDependencies(PitchParams pp, Path zipRoot) {
|
||||
|
||||
GRSService grsService =
|
||||
grsManager.getService(grsManager.get(pp));
|
||||
YAMLOptions yOpts = YAMLOptions.build(pp, grsService, diskService);
|
||||
log.debug("fetchYAMLDependencies: yOpts={}", yOpts);
|
||||
|
||||
try {
|
||||
|
||||
if (yOpts != null && yOpts.hasLogo()) {
|
||||
String logoUrl = yOpts.fetchLogo(pp);
|
||||
String logoName = FilenameUtils.getName(logoUrl);
|
||||
|
||||
Path zipAssetsPath =
|
||||
diskService.ensure(zipRoot.resolve(ZIP_ASSETS_DIR));
|
||||
diskService.download(pp, zipAssetsPath,
|
||||
logoUrl, logoName, grsManager.get(pp).getHeaders());
|
||||
log.debug("fetchYAMLDependencies: downloaded logo={}", logoUrl);
|
||||
}
|
||||
|
||||
} catch (Exception lex) {
|
||||
log.warn("fetchYAMLDependencies: logo ex={}", lex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Prune unused PITCHME.yaml dependencies from zip archive.
|
||||
*/
|
||||
private void pruneYAMLDependencies(PitchParams pp, Path zipRoot) {
|
||||
|
||||
GRSService grsService =
|
||||
grsManager.getService(grsManager.get(pp));
|
||||
YAMLOptions yOpts = YAMLOptions.build(pp, grsService, diskService);
|
||||
log.debug("pruneYAMLDependencies: yOpts={}", yOpts);
|
||||
Path destPath = zipRoot.resolve(ZIP_ASSETS_DIR);
|
||||
String liveRevealVersion =
|
||||
runtime.config("gitpitch.dependency.revealjs");
|
||||
if(yOpts != null && yOpts.fetchRevealVersion(pp) != null) {
|
||||
liveRevealVersion = yOpts.fetchRevealVersion(pp);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* Strip Reveal.js distributions (X.y.z) unused by GitPitch.
|
||||
*/
|
||||
for(String distroVersion : REVEALJS_DISTRO_VERSIONS) {
|
||||
|
||||
if(!distroVersion.equals(liveRevealVersion)) {
|
||||
|
||||
Path distroPath =
|
||||
buildLibraryPath(destPath, "reveal.js", distroVersion);
|
||||
log.debug("pruneYAMLDependencies: removing distro={}",
|
||||
distroPath);
|
||||
|
||||
diskService.deepDelete(distroPath.toFile());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception mex) {
|
||||
log.warn("pruneYAMLDependencies: unused plugin assets ex={}", mex);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* If Math Slides not enabled within PITCHME.yaml, strip
|
||||
* Reveal.js math plugin file dependencies from zip.
|
||||
*/
|
||||
if (yOpts == null || !yOpts.mathEnabled(pp)) {
|
||||
|
||||
Path mathPluginPath =
|
||||
buildLibraryPath(destPath,
|
||||
"reveal.js",
|
||||
liveRevealVersion,
|
||||
"plugin/math");
|
||||
log.debug("pruneYAMLDependencies: removing mathPlugin={}",
|
||||
mathPluginPath);
|
||||
|
||||
diskService.deepDelete(mathPluginPath.toFile());
|
||||
}
|
||||
|
||||
} catch (Exception mex) {
|
||||
log.warn("pruneYAMLDependencies: math config assets ex={}", mex);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* If Chart slides not enabled within PITCHME.yaml, strip
|
||||
* Reveal.js charts plugin file dependencies from zip.
|
||||
*/
|
||||
if (yOpts == null || !yOpts.fetchCharts(pp)) {
|
||||
|
||||
Path chartPluginPath =
|
||||
buildLibraryPath(destPath,
|
||||
"reveal.js",
|
||||
liveRevealVersion,
|
||||
"plugin/chart");
|
||||
log.debug("pruneYAMLDependencies: removing chartPlugin={}",
|
||||
chartPluginPath);
|
||||
|
||||
diskService.deepDelete(chartPluginPath.toFile());
|
||||
}
|
||||
|
||||
} catch (Exception mex) {
|
||||
log.warn("pruneYAMLDependencies: math config assets ex={}", mex);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* Strip Reveal.js standard dist plugins unused by GitPitch.
|
||||
*/
|
||||
for(String pluginName : OFFLINE_UNUSED_PLUGINS) {
|
||||
|
||||
Path unusedPath =
|
||||
buildLibraryPath(destPath,
|
||||
"reveal.js",
|
||||
liveRevealVersion,
|
||||
"plugin/"+ pluginName);
|
||||
log.debug("pruneYAMLDependencies: removing unused={}",
|
||||
unusedPath);
|
||||
|
||||
diskService.deepDelete(unusedPath.toFile());
|
||||
}
|
||||
|
||||
} catch (Exception mex) {
|
||||
log.warn("pruneYAMLDependencies: unused plugin assets ex={}", mex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Build PITCHME.zip.
|
||||
*/
|
||||
private int buildZip(PitchParams pp, Path zipRoot) {
|
||||
|
||||
/*
|
||||
* Remove PITCHME_ONLINE_MD from zip directory.
|
||||
*/
|
||||
Path onlinePath = zipRoot.resolve(PITCHME_ONLINE_PATH);
|
||||
diskService.delete(onlinePath);
|
||||
|
||||
/*
|
||||
* CMD: zip -r PITCHME.zip PITCHME
|
||||
*/
|
||||
String[] cmd = {ZIP_CMD,
|
||||
ZIP_QUIET,
|
||||
ZIP_ALL,
|
||||
PITCHME_ZIP,
|
||||
ZIP_ROOT_DIR};
|
||||
|
||||
Path zipWd = diskService.ensure(pp, pp.pitchme);
|
||||
return shellService.exec(ZIP_CMD, pp, zipWd, cmd);
|
||||
}
|
||||
|
||||
public boolean isEncrypted() {
|
||||
return runtime.configBool("gitpitch.https");
|
||||
}
|
||||
|
||||
public String hostname() {
|
||||
return runtime.config("gitpitch.hostname");
|
||||
}
|
||||
|
||||
public Path devModeFixedDependencies() {
|
||||
String fixedAssets =
|
||||
runtime.config("gitpitch.offline.dev.fixed.assets.home");
|
||||
return Paths.get(fixedAssets);
|
||||
}
|
||||
|
||||
public Path prodModeDependenciesJar() {
|
||||
String jarAssets =
|
||||
runtime.config("gitpitch.offline.prod.fixed.assets.home");
|
||||
return Paths.get(jarAssets);
|
||||
}
|
||||
|
||||
private Path buildLibraryPath(Path basePath,
|
||||
String libName,
|
||||
String libVersion) {
|
||||
return buildLibraryPath(basePath, libName, libVersion, null);
|
||||
}
|
||||
|
||||
private Path buildLibraryPath(Path basePath,
|
||||
String libName,
|
||||
String libVersion,
|
||||
String dirName) {
|
||||
if(dirName != null)
|
||||
return Paths.get(basePath.toString(), libName, libVersion, dirName);
|
||||
else
|
||||
return Paths.get(basePath.toString(), libName, libVersion);
|
||||
}
|
||||
|
||||
private static final String ZIP_ROOT_DIR = "PITCHME";
|
||||
private static final String ZIP_MD_DIR = "assets/md";
|
||||
private static final String ZIP_MD_ASSETS_DIR = "assets/md/assets";
|
||||
private static final String ZIP_ASSETS_DIR = "assets";
|
||||
private static final String PITCHME_ONLINE_MD = "PITCHME.mdo";
|
||||
private static final String PITCHME_OFFLINE_MD = "PITCHME.md";
|
||||
private static final String PITCHME_ONLINE_PATH =
|
||||
ZIP_MD_DIR + "/" + PITCHME_ONLINE_MD;
|
||||
private static final String PITCHME_OFFLINE_PATH =
|
||||
ZIP_MD_DIR + "/" + PITCHME_OFFLINE_MD;
|
||||
private static final String PITCHME_ZIP = "PITCHME.zip";
|
||||
private static final String PITCHME_CSS = "PITCHME.css";
|
||||
private static final String INDEX_HTML = "index.html";
|
||||
private static final String SLIDESHOW_HTML = "pitchme.html";
|
||||
private static final String MENU_HTML = "menu.html";
|
||||
private static final String FIXED_ASSETS = "/public/libs";
|
||||
private static final String FIXED_ASSETS_MATH = "/public/libs-math";
|
||||
private static final String ZIP_CMD = "zip";
|
||||
private static final String ZIP_QUIET = "-q";
|
||||
private static final String ZIP_ALL = "-r";
|
||||
private static final String ENABLED = "true";
|
||||
private static final int STATUS_OK = 0;
|
||||
private static final int STATUS_UNDEF = 999;
|
||||
|
||||
private static final List<String> REVEALJS_DISTRO_VERSIONS =
|
||||
java.util.Arrays.asList("3.3.1", "3.4.1", "3.5.0");
|
||||
|
||||
private static final List<String> OFFLINE_UNUSED_PLUGINS =
|
||||
java.util.Arrays.asList("multiplex",
|
||||
"notes-server",
|
||||
"search",
|
||||
"zoom-js",
|
||||
"print-pdf");
|
||||
private final ConcurrentHashMap<String, CountDownLatch> zipLatchMap =
|
||||
new ConcurrentHashMap();
|
||||
}
|
|
@ -1,293 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.models.GitRepoModel;
|
||||
import com.gitpitch.models.Markdown;
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.models.SlideshowModel;
|
||||
import com.gitpitch.policies.CacheTimeout;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import play.Logger;
|
||||
import play.cache.*;
|
||||
import play.libs.ws.*;
|
||||
|
||||
import javax.inject.*;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/*
|
||||
* Support service for controllers.PitchController actions.
|
||||
*/
|
||||
@Singleton
|
||||
public class PitchService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final static String PITCHME_PDF = "PITCHME.pdf";
|
||||
private final static String PITCHME_ZIP = "PITCHME.zip";
|
||||
private final static String PITCHME_ZIP_DIR = "PITCHME";
|
||||
private final CacheApi pitchCache;
|
||||
private final DiskService diskService;
|
||||
private final GitService gitService;
|
||||
private final PrintService printService;
|
||||
private final OfflineService offlineService;
|
||||
private final CacheTimeout cacheTimeout;
|
||||
|
||||
@Inject
|
||||
public PitchService(CacheApi pitchCache,
|
||||
DiskService diskService,
|
||||
GitService gitService,
|
||||
PrintService printService,
|
||||
OfflineService offlineService,
|
||||
CacheTimeout cacheTimeout) {
|
||||
|
||||
this.pitchCache = pitchCache;
|
||||
this.diskService = diskService;
|
||||
this.gitService = gitService;
|
||||
this.printService = printService;
|
||||
this.offlineService = offlineService;
|
||||
this.cacheTimeout = cacheTimeout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return cached GitRepoModel, else Optional.empty.
|
||||
*/
|
||||
public Optional<GitRepoModel> cachedRepo(PitchParams pp) {
|
||||
|
||||
String grmKey = GitRepoModel.genKey(pp);
|
||||
log.debug("cachedRepo: grmKey={}", grmKey);
|
||||
return Optional.ofNullable(pitchCache.get(grmKey));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return GitRepoModel.
|
||||
*/
|
||||
public GitRepoModel fetchRepo(PitchParams pp) {
|
||||
|
||||
log.debug("fetchRepo: pp={}", pp);
|
||||
CountDownLatch repoLatch = gitService.fetchRepo(pp);
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* Block until GitService.repoFetch() completes.
|
||||
* On success the GitService.repoFetch() will
|
||||
* populate the pitchCache with a valid RepoModel
|
||||
* for /{user}/{repo}/{branch}. On failure, null.
|
||||
*/
|
||||
repoLatch.await();
|
||||
} catch (Exception ex) {
|
||||
log.warn("fetchRepo: pp={}, repoLatch.await ex={}", pp, ex);
|
||||
}
|
||||
|
||||
Optional<GitRepoModel> grmo = cachedRepo(pp);
|
||||
GitRepoModel grm = grmo.orElse(null);
|
||||
log.debug("fetchRepo: pp={}, returning grm={}", pp, grm);
|
||||
|
||||
return grm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return cached SlideshowModel, else Optional.empty.
|
||||
*/
|
||||
public Optional<SlideshowModel> cachedYAML(PitchParams pp) {
|
||||
|
||||
String ssmKey = SlideshowModel.genKey(pp);
|
||||
return Optional.ofNullable(pitchCache.get(ssmKey));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return SlideshowModel.
|
||||
*/
|
||||
public SlideshowModel fetchYAML(PitchParams pp) {
|
||||
|
||||
log.debug("fetchYAML: pp={}", pp);
|
||||
CountDownLatch slideshowLatch = gitService.fetchYAML(pp);
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* Block until GitService.fetchYAML() completes.
|
||||
* On success the GitService.fetchYAML() will
|
||||
* populate the pitchCache with a valid SlideshowModel
|
||||
* for /{user}/{repo}/{branch}. On failure, null.
|
||||
*/
|
||||
slideshowLatch.await();
|
||||
} catch (Exception ex) {
|
||||
log.warn("fetchYAML: pp={}, slideshowLatch.await ex={}", pp, ex);
|
||||
}
|
||||
|
||||
Optional<SlideshowModel> ssmo = cachedYAML(pp);
|
||||
SlideshowModel ssm = ssmo.orElse(null);
|
||||
log.debug("fetchYAML: pp={}, returning ssm={}", pp, ssm);
|
||||
|
||||
return ssm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return cached MarkdownModel, else Optional.empty.
|
||||
*/
|
||||
public Optional<Markdown> cachedMarkdown(PitchParams pp) {
|
||||
|
||||
String mdmKey = MarkdownModel.genKey(pp);
|
||||
return Optional.ofNullable(pitchCache.get(mdmKey));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return RepoModel.
|
||||
*/
|
||||
public Markdown fetchMarkdown(PitchParams pp) {
|
||||
|
||||
log.debug("fetchMarkdown: pp={}", pp);
|
||||
CountDownLatch markdownLatch = gitService.fetchMarkdown(pp);
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* Block until GitService.fetchMarkdown() completes.
|
||||
* On success the GitService.fetchMarkdown() will
|
||||
* populate the pitchCache with a valid MarkdownModel
|
||||
* for /{user}/{repo}/{branch}. On failure, null.
|
||||
*/
|
||||
markdownLatch.await();
|
||||
} catch (Exception ex) {
|
||||
log.warn("fetchMarkdown: pp={}, markdownLatch.await ex={}", pp, ex);
|
||||
}
|
||||
|
||||
Optional<Markdown> mdmo = cachedMarkdown(pp);
|
||||
Markdown mdm = mdmo.orElse(null);
|
||||
log.debug("fetchMarkdown: pp={}, returning mdm={}", pp, mdm);
|
||||
|
||||
return mdm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return cached PITCHME.pdf, else Optional.empty.
|
||||
*/
|
||||
public Optional<File> cachedPDF(PitchParams pp) {
|
||||
|
||||
File pdfFile = diskService.asFile(pp, pp.PDF());
|
||||
long pdfAge = System.currentTimeMillis() - pdfFile.lastModified();
|
||||
|
||||
log.debug("cachedPDF: pdfAge={}, max={}, file={}",
|
||||
pdfAge, cacheTimeout.pdf(pp), pdfFile);
|
||||
|
||||
if (pdfAge > cacheTimeout.pdf(pp)) {
|
||||
diskService.delete(pp, pp.PDF());
|
||||
}
|
||||
|
||||
return pdfFile.exists() ? Optional.of(pdfFile) : Optional.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return PITCHME.pdf.
|
||||
*/
|
||||
public File fetchPDF(PitchParams pp) {
|
||||
|
||||
log.debug("fetchPDF: pp={}", pp);
|
||||
CountDownLatch pdfLatch = printService.fetchPDF(pp);
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* Block until PrintService.fetchPDF() completes.
|
||||
* On success the PrintService.fetchPDF() will
|
||||
* have built PITCHME.pdf on the file system
|
||||
* for /{user}/{repo}/{branch}. On failure, null.
|
||||
*/
|
||||
pdfLatch.await();
|
||||
} catch (Exception ex) {
|
||||
log.warn("fetchPDF: pp={}, pdfLatch.await ex={}", pp, ex);
|
||||
}
|
||||
|
||||
Optional<File> pdfo = cachedPDF(pp);
|
||||
File pdf = pdfo.orElse(null);
|
||||
log.debug("fetchPDF: pp={}, returning pdf={}", pp, pdf);
|
||||
|
||||
return pdf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return cached PITCHME.zip, else Optional.empty.
|
||||
*/
|
||||
public Optional<File> cachedZip(PitchParams pp) {
|
||||
|
||||
Path zipPath = diskService.ensure(pp, pp.pitchme);
|
||||
File zipFile = zipPath.resolve(PITCHME_ZIP).toFile();
|
||||
long zipAge = System.currentTimeMillis() - zipFile.lastModified();
|
||||
|
||||
log.debug("cachedZip: zipAge={}, max={}, file={}",
|
||||
zipAge, cacheTimeout.zip(pp), zipFile);
|
||||
|
||||
if (zipAge > cacheTimeout.zip(pp)) {
|
||||
diskService.delete(zipPath.resolve(PITCHME_ZIP));
|
||||
diskService.deepDelete(zipPath.resolve(PITCHME_ZIP_DIR).toFile());
|
||||
log.debug("cachedZip: deleted expired zip artifacts.");
|
||||
}
|
||||
|
||||
return zipFile.exists() ? Optional.of(zipFile) : Optional.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return PITCHME.zip.
|
||||
*/
|
||||
public File fetchZip(PitchParams pp) {
|
||||
|
||||
log.debug("fetchZip: pp={}", pp);
|
||||
CountDownLatch zipLatch =
|
||||
offlineService.fetchZip(pp, cachedYAML(pp));
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* Block until OfflineService.fetchZip() completes.
|
||||
* On success the OfflineService.fetchZip() will
|
||||
* have built PITCHME.zip on the file system
|
||||
* for /{user}/{repo}/{branch}. On failure, null.
|
||||
*/
|
||||
zipLatch.await();
|
||||
} catch (Exception ex) {
|
||||
log.warn("fetchZip: pp={}, zipLatch.await ex={}", pp, ex);
|
||||
}
|
||||
|
||||
Optional<File> zipo = cachedZip(pp);
|
||||
File zip = zipo.orElse(null);
|
||||
log.debug("fetchZip: pp={}, returning zip={}", pp, zip);
|
||||
|
||||
return zip;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return file at path, else Optional.empty.
|
||||
*/
|
||||
public Optional<File> raw(PitchParams pp, String path) {
|
||||
|
||||
File rawFile = diskService.asFile(pp, path);
|
||||
return rawFile.exists() ? Optional.of(rawFile) : Optional.empty();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,209 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.executors.BackEndThreads;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.utils.YAMLOptions;
|
||||
import com.gitpitch.policies.Runtime;
|
||||
import play.Logger;
|
||||
|
||||
import javax.inject.*;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/*
|
||||
* PITCHME.pdf document print service.
|
||||
*/
|
||||
@Singleton
|
||||
public class PrintService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private DiskService diskService;
|
||||
private ShellService shellService;
|
||||
private BackEndThreads backEndThreads;
|
||||
private Runtime runtime;
|
||||
|
||||
@Inject
|
||||
public PrintService(DiskService diskService,
|
||||
ShellService shellService,
|
||||
BackEndThreads backEndThreads,
|
||||
Runtime runtime) {
|
||||
|
||||
this.diskService = diskService;
|
||||
this.shellService = shellService;
|
||||
this.backEndThreads = backEndThreads;
|
||||
this.runtime = runtime;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate and fetch PITCHME.pdf.
|
||||
*/
|
||||
public CountDownLatch fetchPDF(PitchParams pp) {
|
||||
|
||||
log.debug("fetchPDF: pp={}", pp);
|
||||
|
||||
final String pdfKey = MarkdownModel.genKey(pp);
|
||||
|
||||
CountDownLatch freshLatch = new CountDownLatch(1);
|
||||
CountDownLatch activeLatch =
|
||||
pdfLatchMap.putIfAbsent(pdfKey, freshLatch);
|
||||
|
||||
if (activeLatch != null) {
|
||||
/*
|
||||
* A non-null activeLatch implies a fetchPDF()
|
||||
* operation is already in progress for the current
|
||||
* /{user}/{repo}?b={branch}.
|
||||
*/
|
||||
log.debug("fetchPDF: pp={}, already in progress, " +
|
||||
"returning existing activeLatch={}", pp, activeLatch);
|
||||
return activeLatch;
|
||||
|
||||
} else {
|
||||
|
||||
CompletableFuture<Void> syncFuture =
|
||||
CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
Path branchPath = diskService.ensure(pp, pp.pitchme);
|
||||
int pdfStatus = generatePDF(pp);
|
||||
|
||||
if (pdfStatus != STATUS_OK) {
|
||||
log.warn("fetchPDF: pp={}, fetch status={}", pp, pdfStatus);
|
||||
}
|
||||
|
||||
/*
|
||||
* Current operation completed, so remove latch associated
|
||||
* with operation from pdfLatchMap to permit future
|
||||
* operations on this /{user}/{repo}?b={branch}.
|
||||
*/
|
||||
releaseCountDownLatch(pdfLatchMap, pdfKey);
|
||||
|
||||
/*
|
||||
* Operation completed, valid result cached, no return required.
|
||||
*/
|
||||
return null;
|
||||
|
||||
}, backEndThreads.POOL)
|
||||
.handle((result, error) -> {
|
||||
|
||||
if (error != null) {
|
||||
|
||||
log.warn("fetchPDF: pp={}, fetch error={}", pp, error);
|
||||
releaseCountDownLatch(pdfLatchMap, pdfKey);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
return freshLatch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Call when fetchXXX operation has completed either
|
||||
* successfully or on error. Remove latch associated with
|
||||
* operation from xxxLatchMap to permit future operations
|
||||
* on /{user}/{repo}?b={branch} associated with latchKey.
|
||||
*/
|
||||
private void releaseCountDownLatch(ConcurrentHashMap<String, CountDownLatch> latchMap,
|
||||
String latchKey) {
|
||||
|
||||
CountDownLatch completedLatch = latchMap.remove(latchKey);
|
||||
|
||||
if (completedLatch != null) {
|
||||
completedLatch.countDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate PDF using DeckTape command line service.
|
||||
*/
|
||||
private int generatePDF(PitchParams pp) {
|
||||
|
||||
log.debug("generatePDF: pp={}", pp);
|
||||
Path branchPath = diskService.ensure(pp);
|
||||
diskService.delete(pp, pp.PDF());
|
||||
String filePath = diskService.asFile(pp, pp.PDF()).toString();
|
||||
|
||||
boolean printFrags = false;
|
||||
try {
|
||||
printFrags =
|
||||
YAMLOptions.build(pp, null, diskService).printFrags(pp);
|
||||
} catch(Exception ex) {}
|
||||
|
||||
String slideshowUrl =
|
||||
com.gitpitch.controllers.routes.PitchController.slideshow(pp.user,
|
||||
pp.repo,
|
||||
pp.branch,
|
||||
pp.grs,
|
||||
pp.theme,
|
||||
pp.pitchme,
|
||||
pp.notes,
|
||||
null,
|
||||
Boolean.toString(printFrags),
|
||||
null)
|
||||
.absoluteURL(isEncrypted(),
|
||||
hostname());
|
||||
|
||||
String deckTape = diskService.decktape();
|
||||
String[] cmd =
|
||||
{ deckTape, REVEAL, slideshowUrl, filePath, decktapeArgs()};
|
||||
int generated = shellService.exec(GIT_PDF, pp, branchPath, cmd);
|
||||
|
||||
if (generated != STATUS_OK) {
|
||||
log.warn("generatePDF: pp={}, generate status={}", pp, generated);
|
||||
}
|
||||
|
||||
return generated;
|
||||
}
|
||||
|
||||
public boolean isEncrypted() {
|
||||
return runtime.configBool("gitpitch.https");
|
||||
}
|
||||
|
||||
public String hostname() {
|
||||
return runtime.config("gitpitch.hostname");
|
||||
}
|
||||
|
||||
private String decktapeArgs() {
|
||||
String args = runtime.config("gitpitch.decktape.args");
|
||||
return (args != null) ? args : "";
|
||||
}
|
||||
|
||||
private static final String REVEAL = "reveal";
|
||||
private static final String PITCHME_PDF = "PITCHME.pdf";
|
||||
private static final String GIT_PDF = "pdf";
|
||||
private static final int STATUS_OK = 0;
|
||||
|
||||
private final ConcurrentHashMap<String, CountDownLatch> pdfLatchMap =
|
||||
new ConcurrentHashMap();
|
||||
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import play.Logger;
|
||||
|
||||
import javax.inject.*;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/*
|
||||
* Shell command execution service.
|
||||
*/
|
||||
@Singleton
|
||||
public class ShellService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
public int exec(String op, PitchParams pp, Path wd, String... cmd) {
|
||||
|
||||
int resp = STATUS_UDEF;
|
||||
|
||||
try {
|
||||
|
||||
long startProc = System.currentTimeMillis();
|
||||
|
||||
Process cmdProc = new ProcessBuilder(cmd).inheritIO()
|
||||
.directory(wd.toFile())
|
||||
.start();
|
||||
|
||||
resp = cmdProc.waitFor();
|
||||
log.debug("exec: op={}, pp={}, time taken={}", op, pp,
|
||||
(System.currentTimeMillis() - startProc));
|
||||
|
||||
|
||||
} catch (IOException ioex) {
|
||||
log.warn("exec: op={}, pp={}, ioex={}", op, pp, ioex);
|
||||
resp = STATUS_IO_EX;
|
||||
} catch (InterruptedException iex) {
|
||||
log.warn("exec: op={}, pp={}, iex={}", op, pp, iex);
|
||||
resp = STATUS_INT_EX;
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
private static final int STATUS_OK = 0;
|
||||
private static final int STATUS_IO_EX = -777;
|
||||
private static final int STATUS_INT_EX = -888;
|
||||
private static final int STATUS_UDEF = -999;
|
||||
}
|
|
@ -1,271 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.utils.YAMLOptions;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import java.util.*;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* PITCHME.md feature-shortcuts support service.
|
||||
*/
|
||||
@Singleton
|
||||
public class ShortcutsService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
public String process(String md, PitchParams pp, YAMLOptions yOpts) {
|
||||
|
||||
String processed = md;
|
||||
|
||||
try {
|
||||
int faCycles = 5; // Prevent infinite loop.
|
||||
while(fontAwesomeFound(processed) && faCycles > 0) {
|
||||
String expanded = expandFontAwesome(processed);
|
||||
faCycles = processed.equals(expanded) ? 0 : (faCycles-1);
|
||||
processed = expanded;
|
||||
}
|
||||
} catch(Exception ex) {}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
public boolean listFragmentFound(String md) {
|
||||
boolean found = false;
|
||||
if(md != null) {
|
||||
String trimmed = md.trim();
|
||||
if(trimmed.startsWith(MarkdownModel.MD_LIST_FRAG_OPEN) &&
|
||||
trimmed.endsWith(MarkdownModel.MD_LIST_FRAG_CLOSE)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public boolean codeFragmentFound(String md) {
|
||||
boolean found = false;
|
||||
if(md != null) {
|
||||
if(md.startsWith(MarkdownModel.MD_CODE_FRAG_OPEN)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public boolean titleHintFound(String md) {
|
||||
boolean found = false;
|
||||
if(md != null) {
|
||||
if(md.startsWith(MarkdownModel.MD_TITLE_HINT_OPEN)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public boolean fontAwesomeFound(String md) {
|
||||
boolean found = false;
|
||||
if(md != null) {
|
||||
if(md.contains(MarkdownModel.MD_FA_OPEN)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand shortcut syntax for list fragment with fully expanded
|
||||
* HTML comment syntax.
|
||||
*/
|
||||
public String expandListFragment(String md) {
|
||||
int fragCloseIdx = md.lastIndexOf(MarkdownModel.MD_LIST_FRAG_CLOSE);
|
||||
return md.substring(0, fragCloseIdx) + FRAGMENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand shortcut syntax for code fragment with fully expanded
|
||||
* HTML span syntax with data-code-focus class.
|
||||
*/
|
||||
public String expandCodeFragment(String md) {
|
||||
|
||||
try {
|
||||
String codeFragRange = null;
|
||||
String codeFragNote = null;
|
||||
|
||||
int codeFragStart =
|
||||
md.indexOf(MarkdownModel.MD_CODE_FRAG_OPEN);
|
||||
int codeFragEnd =
|
||||
md.indexOf(MarkdownModel.MD_CODE_FRAG_CLOSE);
|
||||
|
||||
if(codeFragEnd > codeFragStart) {
|
||||
codeFragRange =
|
||||
md.substring(codeFragStart+2, codeFragEnd);
|
||||
}
|
||||
|
||||
int codeFragNoteStart =
|
||||
md.indexOf(MarkdownModel.MD_CODE_FRAG_NOTE_OPEN);
|
||||
int codeFragNoteEnd =
|
||||
md.lastIndexOf(MarkdownModel.MD_CODE_FRAG_NOTE_CLOSE);
|
||||
|
||||
if(codeFragNoteEnd > codeFragNoteStart) {
|
||||
codeFragNote =
|
||||
md.substring(codeFragNoteStart+1, codeFragNoteEnd);
|
||||
}
|
||||
|
||||
if(codeFragRange != null) {
|
||||
md = buildCodeFragment(codeFragRange, codeFragNote);
|
||||
}
|
||||
|
||||
} catch(Exception cfex) {
|
||||
} finally {
|
||||
return md;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand title-hint shortcut syntax into corresponding
|
||||
* HTML hidden span for detection by menu.js.
|
||||
*/
|
||||
public String expandTitleHint(String md) {
|
||||
|
||||
try {
|
||||
|
||||
int hintStart =
|
||||
md.indexOf(MarkdownModel.MD_TITLE_HINT_OPEN) +
|
||||
MarkdownModel.MD_TITLE_HINT_OPEN.length();
|
||||
int hintEnd =
|
||||
md.lastIndexOf(MarkdownModel.MD_TITLE_HINT_CLOSE);
|
||||
|
||||
if(hintEnd > hintStart) {
|
||||
String hint = md.substring(hintStart, hintEnd);
|
||||
md = new StringBuffer(TITLE_HINT_SPAN_OPEN)
|
||||
.append(hint)
|
||||
.append(TITLE_HINT_SPAN_CLOSE)
|
||||
.toString();
|
||||
}
|
||||
|
||||
} catch(Exception cfex) {
|
||||
} finally {
|
||||
return md;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand shortcut syntax for font-awesome with fully expanded
|
||||
* HTML span syntax with optional text.
|
||||
*/
|
||||
public String expandFontAwesome(String md) {
|
||||
|
||||
String mdLeft = "";
|
||||
String faName = "";
|
||||
String faNote = "";
|
||||
String mdRight = "";
|
||||
String expandedFA = "";
|
||||
|
||||
try {
|
||||
int faOpen = md.indexOf(MarkdownModel.MD_FA_OPEN);
|
||||
int faClose = md.indexOf(MarkdownModel.MD_FA_CLOSE);
|
||||
|
||||
if(faClose > faOpen) { /* faName exists */
|
||||
|
||||
mdLeft = md.substring(0, faOpen);
|
||||
faName =
|
||||
md.substring(faOpen + MarkdownModel.MD_FA_OPEN.length(),
|
||||
faClose);
|
||||
|
||||
String rmd = md.substring(faClose + 1);
|
||||
|
||||
int faNoteOpen = rmd.indexOf(MarkdownModel.MD_FA_NOTE_OPEN);
|
||||
int faNoteClose = rmd.indexOf(MarkdownModel.MD_FA_NOTE_CLOSE);
|
||||
|
||||
if(faNoteOpen == 0) { /* faNote immediately follows faName */
|
||||
|
||||
faNote =
|
||||
rmd.substring(MarkdownModel.MD_FA_NOTE_OPEN.length(),
|
||||
faNoteClose);
|
||||
mdRight = rmd.substring(faNoteClose + 1);
|
||||
} else {
|
||||
mdRight = rmd;
|
||||
}
|
||||
|
||||
expandedFA = buildFontAwesome(faName, faNote);
|
||||
}
|
||||
|
||||
} catch(Exception ex) {
|
||||
} finally {
|
||||
return mdLeft + expandedFA + mdRight;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a HTML fragment for a code fragment based on the
|
||||
* reveal-code-focus plugin syntax:
|
||||
* <span class="fragment current-only" data-code-focus="1-9">Note</span>
|
||||
*/
|
||||
private String buildCodeFragment(String range, String note) {
|
||||
if(note == null) note = "";
|
||||
return new StringBuffer(HTML_CODE_FRAG_OPEN)
|
||||
.append(range)
|
||||
.append(HTML_CODE_FRAG_CLOSE)
|
||||
.append(note)
|
||||
.append(HTML_CODE_FRAG_NOTE_CLOSE)
|
||||
.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a HTML fragment for an FA icon.
|
||||
*/
|
||||
private String buildFontAwesome(String font, String text) {
|
||||
if(text == null) text = "";
|
||||
return new StringBuffer(HTML_FONT_FRAG_OPEN)
|
||||
.append(font)
|
||||
.append(HTML_FONT_FRAG_CLOSE)
|
||||
.append(text)
|
||||
.append(HTML_FONT_FRAG_TEXT_CLOSE)
|
||||
.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Note, the space before opening bracket is intentional
|
||||
* so tag injection can happen directly alongside other
|
||||
* text in the markdown fragment.
|
||||
*/
|
||||
private static final String FRAGMENT =
|
||||
" <!-- .element: class=\"fragment\" -->";
|
||||
private static final String HTML_CODE_FRAG_OPEN =
|
||||
"<span class=\"code-presenting-annotation fragment current-only\" data-code-focus=\"";
|
||||
private static final String HTML_CODE_FRAG_CLOSE = "\">";
|
||||
private static final String HTML_CODE_FRAG_NOTE_CLOSE = "</span>";
|
||||
private static final String TITLE_HINT_SPAN_OPEN =
|
||||
"<span class=\"menu-title\" style=\"display: none\">";
|
||||
private static final String TITLE_HINT_SPAN_CLOSE = "</span>";
|
||||
private static final String HTML_FONT_FRAG_OPEN = "<i class=\"fa fa-";
|
||||
private static final String HTML_FONT_FRAG_CLOSE = "\" aria-hidden=\"true\"> ";
|
||||
private static final String HTML_FONT_FRAG_TEXT_CLOSE = "</i>";
|
||||
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.services.ImageService;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.utils.DelimParams;
|
||||
import com.gitpitch.utils.YAMLOptions;
|
||||
import java.util.*;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* Slide utility service.
|
||||
*/
|
||||
@Singleton
|
||||
public class SlideService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final ImageService imageService;
|
||||
|
||||
@Inject
|
||||
public SlideService(ImageService imageService) {
|
||||
this.imageService = imageService;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build basic slide structure including:
|
||||
*
|
||||
* 1. Clean delimiter and
|
||||
* 2. Optionally slide bg-image based on YAMLOptions.hasImageBg.
|
||||
* 3. Or slide color delimiter.
|
||||
*/
|
||||
public String build(String md,
|
||||
DelimParams dp,
|
||||
PitchParams pp,
|
||||
YAMLOptions yOpts,
|
||||
MarkdownModel mdm) {
|
||||
|
||||
StringBuffer structure = new StringBuffer(mdm.extractDelim(md));
|
||||
|
||||
try {
|
||||
|
||||
structure = new StringBuffer(mdm.extractDelim(md))
|
||||
.append(MarkdownModel.MD_SPACER);
|
||||
|
||||
if (yOpts != null && yOpts.hasImageBg()) {
|
||||
String yamlBg = imageService.buildBackground(pp, yOpts);
|
||||
structure.append(yamlBg).append(MarkdownModel.MD_SPACER);
|
||||
} else {
|
||||
String cbg = buildColorMarkdown(dp);
|
||||
if(cbg != null) {
|
||||
structure.append(cbg).append(MarkdownModel.MD_SPACER);
|
||||
}
|
||||
}
|
||||
|
||||
} catch(Exception ex) {
|
||||
log.warn("build: ex={}", ex);
|
||||
}
|
||||
|
||||
log.debug("build: returning structure={}", structure.toString());
|
||||
|
||||
return structure.toString();
|
||||
}
|
||||
|
||||
public String buildColorBackground(String md,
|
||||
DelimParams dp,
|
||||
PitchParams pp,
|
||||
YAMLOptions yOpts,
|
||||
MarkdownModel mdm) {
|
||||
|
||||
StringBuffer structure = new StringBuffer(mdm.extractDelim(md));
|
||||
|
||||
try {
|
||||
|
||||
structure = new StringBuffer(mdm.extractDelim(md))
|
||||
.append(MarkdownModel.MD_SPACER);
|
||||
|
||||
String bg = buildColorMarkdown(dp);
|
||||
if(bg != null) {
|
||||
structure.append(bg).append(MarkdownModel.MD_SPACER);
|
||||
}
|
||||
|
||||
} catch(Exception ex) {
|
||||
log.warn("buildColorDelim: ex={}", ex);
|
||||
}
|
||||
|
||||
log.debug("buildColorDelim: returning structure={}", structure.toString());
|
||||
return structure.toString();
|
||||
}
|
||||
|
||||
private String buildColorMarkdown(DelimParams dp) {
|
||||
String bgColor = dp.get(MarkdownModel.DELIM_QUERY_COLOR, null);
|
||||
String bg = MarkdownModel.MD_BG_COLOR + bgColor + MarkdownModel.MD_CLOSER;
|
||||
return bgColor != null ? bg : null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.utils.YAMLOptions;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import java.util.*;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* PITCHME.md splash-slide support service.
|
||||
*/
|
||||
@Singleton
|
||||
public class SplashService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
/*
|
||||
* Generate presentation splash-slide markdown.
|
||||
*/
|
||||
public String build(String md, YAMLOptions yOpts, String delim) {
|
||||
|
||||
return new StringBuffer(SPLASH_OPEN).append(SPLASH_LOGO_URL)
|
||||
.append(SPLASH_PAD)
|
||||
.append(SPLASH_LOGO_SIZE)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.append(SPLASH_TOC)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.append(SPLASH_CLOSE)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.append(delim)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.append(md)
|
||||
.toString();
|
||||
}
|
||||
|
||||
private static final String SPLASH_OPEN =
|
||||
"<section data-background-color='black' data-background-image=\"";
|
||||
private static final String SPLASH_LOGO_URL =
|
||||
"https://gitpitch.com/gp-splash.svg";
|
||||
private static final String SPLASH_PAD = "\" ";
|
||||
private static final String SPLASH_LOGO_SIZE =
|
||||
"data-background-size='40%'>";
|
||||
private static final String SPLASH_TOC =
|
||||
"<span class='menu-title' style='display: none'>GitPitch</span>";
|
||||
private static final String SPLASH_CLOSE = "</section>";
|
||||
}
|
|
@ -1,205 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.models.MarkdownModel;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import com.gitpitch.utils.DelimParams;
|
||||
import java.util.*;
|
||||
import javax.inject.*;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* PITCHME.md video support service.
|
||||
*/
|
||||
@Singleton
|
||||
public class VideoService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
/*
|
||||
* Determine if video link is valid based on MP4 extension
|
||||
* or if link to popular video hosting services.
|
||||
*/
|
||||
public boolean isVideo(String videoLink) {
|
||||
|
||||
boolean isVideo = false;
|
||||
|
||||
if (videoLink != null) {
|
||||
|
||||
if (videoLink.toLowerCase().endsWith(VIDEO_MP4)) {
|
||||
isVideo = true;
|
||||
} else if (videoLink.contains(YOUTUBE_EMBED)) {
|
||||
isVideo = true;
|
||||
} else if (videoLink.contains(VIMEO_EMBED)) {
|
||||
isVideo = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return isVideo;
|
||||
}
|
||||
|
||||
public String buildVideo(String videoLink) {
|
||||
|
||||
if (videoLink.contains(YOUTUBE_EMBED)) {
|
||||
|
||||
/*
|
||||
* Build YouTube <iframe> tag.
|
||||
*
|
||||
* Example link:
|
||||
* https://www.youtube.com/embed/mkiDkkdGGAQ
|
||||
*
|
||||
* Example link with offset start time:
|
||||
* https://www.youtube.com/embed/mkiDkkdGGAQ?start=121
|
||||
*/
|
||||
|
||||
String ifrOps = (videoLink.contains("?")) ?
|
||||
YTUBE_IFR_OPS_APPEND : YTUBE_IFR_OPS;
|
||||
|
||||
return new StringBuffer(YTUBE_DIV_OPEN).append(YTUBE_IFR_OPEN)
|
||||
.append(videoLink)
|
||||
.append(ifrOps)
|
||||
.append(YTUBE_IFR_CLSE)
|
||||
.append(YTUBE_DIV_CLSE)
|
||||
.toString();
|
||||
|
||||
} else if (videoLink.contains(VIMEO_EMBED)) {
|
||||
|
||||
/*
|
||||
* Build Vimeo <iframe> tag.
|
||||
*
|
||||
* Example link:
|
||||
* https://player.vimeo.com/video/111525512
|
||||
*/
|
||||
return new StringBuffer(VIMEO_DIV_OPEN).append(VIMEO_IFR_OPEN)
|
||||
.append(videoLink)
|
||||
.append(VIMEO_IFR_FULL)
|
||||
.append(VIMEO_IFR_CLSE)
|
||||
.append(VIMEO_DIV_CLSE)
|
||||
.toString();
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Build Reveal.js HTML5 <video> tag.
|
||||
*
|
||||
* Example link:
|
||||
* http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4
|
||||
*/
|
||||
return new StringBuffer(RJS_VID_OPEN).append(RJS_VID_STRH)
|
||||
.append(RJS_VID_AUTO)
|
||||
.append(RJS_VID_SRC)
|
||||
.append(videoLink)
|
||||
.append(RJS_VID_CLSE)
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String buildBackground(String md,
|
||||
DelimParams dp,
|
||||
PitchParams pp,
|
||||
MarkdownModel mdm) {
|
||||
|
||||
String bgUrl = dp.get(MarkdownModel.DELIM_QUERY_VIDEO, "#");
|
||||
bgUrl = mdm.linkLive(pp, bgUrl);
|
||||
String loop = dp.get(MarkdownModel.DELIM_QUERY_LOOP);
|
||||
String muted = dp.get(MarkdownModel.DELIM_QUERY_MUTED);
|
||||
|
||||
StringBuffer buf = new StringBuffer(MarkdownModel.MD_SPACER)
|
||||
.append(MarkdownModel.MD_SPACER)
|
||||
.append(MarkdownModel.MD_VIDEO_OPEN)
|
||||
.append(bgUrl)
|
||||
.append(MarkdownModel.MD_VIDEO_OPEN_END);
|
||||
|
||||
if(Boolean.parseBoolean(loop)) {
|
||||
buf.append(MarkdownModel.MD_VIDEO_LOOP);
|
||||
}
|
||||
|
||||
if(Boolean.parseBoolean(muted)) {
|
||||
buf.append(MarkdownModel.MD_VIDEO_MUTED);
|
||||
}
|
||||
|
||||
buf.append(MarkdownModel.MD_VIDEO_CLOSE)
|
||||
.append(MarkdownModel.MD_SPACER);
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public boolean found(String md) {
|
||||
return (md != null &&
|
||||
(md.contains(DATA_VIDEO_ATTR) || md.contains(DATA_VIDEO_BG_ATTR)));
|
||||
}
|
||||
|
||||
public String offline() {
|
||||
|
||||
return new StringBuffer(OFFLINE_VIDEO).append(SPACER)
|
||||
.append(OFFLINE_NOTICE)
|
||||
.toString();
|
||||
}
|
||||
|
||||
private static final String VIDEO_MP4 = "mp4";
|
||||
/*
|
||||
* Reveal.js Video Tag Frags.
|
||||
*/
|
||||
private static final String RJS_VID_OPEN = "<video data-video=\"true\"";
|
||||
private static final String RJS_VID_STRH = "class=\"stretch\" ";
|
||||
private static final String RJS_VID_AUTO = "data-autoplay ";
|
||||
private static final String RJS_VID_SRC = "src=\"";
|
||||
private static final String RJS_VID_CLSE = "\"></video>";
|
||||
/*
|
||||
* Supported Video Hosting Services.
|
||||
*/
|
||||
private static final String YOUTUBE_EMBED = "youtube.com/embed";
|
||||
private static final String VIMEO_EMBED = "player.vimeo.com/video";
|
||||
/*
|
||||
* YouTube Video Embed Tag Frags.
|
||||
*/
|
||||
private static final String YTUBE_DIV_OPEN = "<div data-video=\"true\" class=\"stretch\">";
|
||||
private static final String YTUBE_IFR_OPEN = "<iframe width=\"100%\" height=\"100%\" src=\"";
|
||||
private static final String YTUBE_IFR_OPS = "?wmode=opaque&rel=0&vq=large\" ";
|
||||
private static final String YTUBE_IFR_OPS_APPEND = "&wmode=opaque&rel=0&vq=large\" ";
|
||||
private static final String YTUBE_IFR_CLSE = "frameborder=\"0\" allowfullscreen></iframe>";
|
||||
private static final String YTUBE_DIV_CLSE = "</div>";
|
||||
/*
|
||||
* Vimeo Video Embed Tag Frags.
|
||||
*/
|
||||
private static final String VIMEO_DIV_OPEN = "<div data-video=\"true\" class=\"stretch\">";
|
||||
private static final String VIMEO_IFR_OPEN = "<iframe width=\"100%\" height=\"100%\" src=\"";
|
||||
private static final String VIMEO_IFR_FULL = "\" webkitallowfullscreen mozallowfullscreen ";
|
||||
private static final String VIMEO_IFR_CLSE = "frameborder=\"0\" allowfullscreen></iframe>";
|
||||
private static final String VIMEO_DIV_CLSE = "</div>";
|
||||
/*
|
||||
* Video Slide Offline Support.
|
||||
*/
|
||||
private static final String OFFLINE_VIDEO = "#### Video Slide Disabled";
|
||||
private static final String OFFLINE_NOTICE = "#### [ GitPitch Offline ]";
|
||||
private static final String DATA_VIDEO_ATTR = "data-video=";
|
||||
private static final String DATA_VIDEO_BG_ATTR = "data-background-video=";
|
||||
private static final String SPACER = "\n";
|
||||
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.services;
|
||||
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import play.Logger;
|
||||
import play.libs.ws.*;
|
||||
|
||||
import javax.inject.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
/*
|
||||
* HTTP(S) web service.
|
||||
*/
|
||||
@Singleton
|
||||
public class WebService {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final WSClient ws;
|
||||
|
||||
@Inject
|
||||
public WebService(WSClient ws) {
|
||||
|
||||
this.ws = ws;
|
||||
}
|
||||
|
||||
public byte[] fetchBytes(PitchParams pp,
|
||||
String source,
|
||||
Map<String,String> headers) {
|
||||
|
||||
byte[] fetched = null;
|
||||
|
||||
try {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
WSResponse downloadResp = download(pp, source, headers);
|
||||
|
||||
if (downloadResp.getStatus() == HttpURLConnection.HTTP_OK) {
|
||||
|
||||
fetched = downloadResp.asByteArray();
|
||||
log.debug("fetchBytes: pp={}, time-taken={} (ms) to " +
|
||||
"read {} bytes from source={}", pp,
|
||||
(System.currentTimeMillis() - start),
|
||||
fetched.length, source);
|
||||
|
||||
} else {
|
||||
|
||||
log.debug("fetchBytes: pp={}, failed status={}, " +
|
||||
"from source={}", pp, downloadResp.getStatus(), source);
|
||||
}
|
||||
} catch(Exception bex) {
|
||||
log.warn("fetchBytes: failed pp={}, from source={}, ex={}",
|
||||
pp, source, bex);
|
||||
}
|
||||
|
||||
return fetched;
|
||||
}
|
||||
|
||||
public String fetchText(PitchParams pp,
|
||||
String source,
|
||||
Map<String,String> headers) {
|
||||
|
||||
byte[] fetched = fetchBytes(pp, source, headers);
|
||||
if(fetched != null)
|
||||
return new String(fetched, StandardCharsets.UTF_8);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Download file from HTTP(s) source url.
|
||||
*/
|
||||
private WSResponse download(PitchParams pp,
|
||||
String source,
|
||||
Map<String,String> headers) {
|
||||
|
||||
WSResponse downloadResp = null;
|
||||
|
||||
try {
|
||||
|
||||
log.debug("download: pp={}, source={}", pp, source);
|
||||
|
||||
final long start = System.currentTimeMillis();
|
||||
|
||||
final WSRequest downloadReq = ws.url(source);
|
||||
|
||||
downloadReq.setHeader(API_CACHE_CONTROL, API_NO_CACHE);
|
||||
|
||||
headers.forEach((k,v) -> {
|
||||
downloadReq.setHeader(k, v);
|
||||
});
|
||||
|
||||
downloadResp =
|
||||
downloadReq.get().toCompletableFuture().get();
|
||||
|
||||
} catch (Exception dex) {
|
||||
log.warn("download: failed pp={}, from source={}, ex={}",
|
||||
pp, source, dex);
|
||||
}
|
||||
|
||||
return downloadResp;
|
||||
}
|
||||
|
||||
private static final String API_HEADER_AUTH = "Authorization";
|
||||
private static final String API_HEADER_TOKEN = "token ";
|
||||
private static final String API_CACHE_CONTROL = "Cache-Control";
|
||||
private static final String API_NO_CACHE = "no-cache";
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.utils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/*
|
||||
* Markdown Delimiter Parameter Parser.
|
||||
*/
|
||||
public class DelimParams {
|
||||
|
||||
private String delimiter;
|
||||
private List<NameValuePair> params = Collections.emptyList();
|
||||
|
||||
private DelimParams(String delimiter) {
|
||||
|
||||
this.delimiter = delimiter;
|
||||
if(delimiter != null && delimiter.contains(QUERY_ON_DELIM)) {
|
||||
int queryIndex = delimiter.indexOf(QUERY_ON_DELIM) + 1;
|
||||
String delimQuery = delimiter.substring(queryIndex);
|
||||
this.params =
|
||||
URLEncodedUtils.parse(delimQuery, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
public static DelimParams build(String delimiter) {
|
||||
return new DelimParams(delimiter);
|
||||
}
|
||||
|
||||
public String get(String param) {
|
||||
return get(param, null);
|
||||
}
|
||||
|
||||
public String get(String param, String defaultValue) {
|
||||
|
||||
if(params != null) {
|
||||
|
||||
Optional<NameValuePair> match =
|
||||
params.stream()
|
||||
.filter(nvp -> nvp.getName().equals(param))
|
||||
.findFirst();
|
||||
|
||||
return match.isPresent() ? match.get().getValue() : defaultValue;
|
||||
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String QUERY_ON_DELIM = "?";
|
||||
|
||||
}
|
|
@ -1,697 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.utils;
|
||||
|
||||
import com.gitpitch.git.GRS;
|
||||
import com.gitpitch.git.vendors.*;
|
||||
import com.gitpitch.models.GitRepoModel;
|
||||
import com.gitpitch.policies.Runtime;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
/*
|
||||
* Rendering model for views.Slideshow.scala.html.
|
||||
*/
|
||||
public class GitRepoRenderer {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final PitchParams _pp;
|
||||
private final GitRepoModel _grm;
|
||||
private final Runtime runtime;
|
||||
private List<GRS> _grsServices;
|
||||
/*
|
||||
* Relative URLs for view components.
|
||||
*/
|
||||
private String _slideshowBase;
|
||||
private String _slideshowURL;
|
||||
private String _markdownURL;
|
||||
/*
|
||||
* Absolute URLs for Git page links.
|
||||
*/
|
||||
private String _orgHub;
|
||||
private String _repoHub;
|
||||
private String _starHub;
|
||||
private String _forkHub;
|
||||
|
||||
private GitRepoRenderer(PitchParams pp, List<GRS> grsServices) {
|
||||
this(pp, null, null, grsServices);
|
||||
}
|
||||
|
||||
private GitRepoRenderer(PitchParams pp,
|
||||
GitRepoModel grm,
|
||||
Runtime runtime,
|
||||
List<GRS> grsServices) {
|
||||
|
||||
this._pp = pp;
|
||||
this._grm = grm;
|
||||
this.runtime = runtime;
|
||||
this._grsServices = grsServices;
|
||||
|
||||
if (grm != null) {
|
||||
|
||||
/*
|
||||
* Initialize properties based on valid repository
|
||||
* data returned on Git Git API as GitRepoModel, if exists.
|
||||
*/
|
||||
|
||||
this._slideshowURL =
|
||||
com.gitpitch.controllers.routes.PitchController
|
||||
.slideshow(_grm.owner(),
|
||||
_grm.name(),
|
||||
_pp.branch,
|
||||
_pp.grs,
|
||||
_pp.theme,
|
||||
_pp.pitchme,
|
||||
_pp.notes, null, null, null).toString();
|
||||
|
||||
this._markdownURL = com.gitpitch.controllers.routes.PitchController
|
||||
.markdown(_pp.grs,
|
||||
_grm.owner(),
|
||||
_grm.name(),
|
||||
_pp.branch,
|
||||
_pp.pitchme).toString();
|
||||
|
||||
Optional<GRS> grso =
|
||||
this._grsServices.stream()
|
||||
.filter(grs -> grs.getType().equals(_pp.grs))
|
||||
.findFirst();
|
||||
|
||||
Optional<GRS> grsoDefault =
|
||||
this._grsServices.stream()
|
||||
.filter(grs -> grs.isDefault())
|
||||
.findFirst();
|
||||
|
||||
String grsSite = null;
|
||||
|
||||
if(grso.isPresent()) {
|
||||
grsSite = grso.get().getSite();
|
||||
} else {
|
||||
if(grsoDefault.isPresent())
|
||||
grsSite = grsoDefault.get().getSite();
|
||||
else
|
||||
grsSite = GRS_GITHUB_COM;
|
||||
}
|
||||
|
||||
this._orgHub = new StringBuffer(grsSite).append(_grm.owner())
|
||||
.toString();
|
||||
|
||||
this._repoHub =
|
||||
new StringBuffer(_orgHub).append(SLASH)
|
||||
.append(this._grm.name())
|
||||
.toString();
|
||||
|
||||
switch(_pp.grs) {
|
||||
|
||||
case GitHub.TYPE:
|
||||
this._starHub =
|
||||
new StringBuffer(this._repoHub).append(SLASH)
|
||||
.append(GRS_GITHUB_STARS)
|
||||
.toString();
|
||||
this._forkHub =
|
||||
new StringBuffer(this._repoHub).append(SLASH)
|
||||
.append(GRS_GITHUB_FORKS)
|
||||
.toString();
|
||||
break;
|
||||
case GitLab.TYPE:
|
||||
this._starHub =
|
||||
new StringBuffer(this._repoHub).append(SLASH)
|
||||
.append(GRS_GITLAB_STARS)
|
||||
.toString();
|
||||
this._forkHub =
|
||||
new StringBuffer(this._repoHub).append(SLASH)
|
||||
.append(GRS_GITLAB_FORKS)
|
||||
.append(_pp.branch)
|
||||
.toString();
|
||||
break;
|
||||
case BitBucket.TYPE:
|
||||
this._starHub =
|
||||
new StringBuffer(this._repoHub).append(SLASH)
|
||||
.append(GRS_BITBUCKET_STARS)
|
||||
.toString();
|
||||
this._forkHub =
|
||||
new StringBuffer(this._repoHub).append(SLASH)
|
||||
.append(GRS_BITBUCKET_FORKS)
|
||||
.toString();
|
||||
break;
|
||||
|
||||
default:
|
||||
this._starHub = "#";
|
||||
this._forkHub = "#";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Initialize properties to non-null defaults as valid Git
|
||||
* repository data is not available.
|
||||
*/
|
||||
|
||||
this._slideshowBase = HTTP_HASH;
|
||||
this._slideshowURL = HTTP_HASH;
|
||||
this._orgHub = HTTP_HASH;
|
||||
this._repoHub = HTTP_HASH;
|
||||
this._starHub = HTTP_HASH;
|
||||
this._forkHub = HTTP_HASH;
|
||||
}
|
||||
}
|
||||
|
||||
public static GitRepoRenderer build(PitchParams pp,
|
||||
GitRepoModel grm,
|
||||
Runtime runtime,
|
||||
List<GRS> grsServices) {
|
||||
|
||||
return new GitRepoRenderer(pp, grm, runtime, grsServices);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return PitchParams on this GitRepoRenderer.
|
||||
*/
|
||||
public PitchParams params() {
|
||||
return _pp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return GitRepoModel on this GitRepoRenderer.
|
||||
*/
|
||||
public GitRepoModel model() {
|
||||
return _grm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return Git {user} name.
|
||||
*/
|
||||
public String user() {
|
||||
return _pp.user;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return Git {repo} name.
|
||||
*/
|
||||
public String repo() {
|
||||
return _pp.repo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return Git {branch} name.
|
||||
*/
|
||||
public String branch() {
|
||||
return _pp.branch;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return Git {pitchme} path.
|
||||
*/
|
||||
public String pitchme() {
|
||||
return (_pp.pitchme != null) ?
|
||||
_pp.pitchme.replaceAll("/", ".") : PITCHME;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return pitch slideshow theme.
|
||||
*/
|
||||
public String theme() {
|
||||
return _pp.theme;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return pitch slideshow grs.
|
||||
*/
|
||||
public String grs() {
|
||||
return _pp.grs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true is branch is GIT_MASTER.
|
||||
*/
|
||||
public boolean isMaster() {
|
||||
return _pp.isMaster();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return pitch slideshow theme.css.
|
||||
*/
|
||||
public String themeCSS() {
|
||||
return _pp.theme + CSS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return relative URL to slideshow.
|
||||
*/
|
||||
public String slideshowURL() {
|
||||
return _slideshowURL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return relative URL to slideshow.
|
||||
*/
|
||||
public String slideshowURL(String theme) {
|
||||
return com.gitpitch.controllers.routes.PitchController
|
||||
.slideshow(_grm.owner(),
|
||||
_grm.name(),
|
||||
_pp.branch,
|
||||
_pp.grs,
|
||||
theme,
|
||||
_pp.pitchme,
|
||||
_pp.notes, null, null, null).toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return absolute URL to slideshow.
|
||||
*/
|
||||
public String slideshowAbs() {
|
||||
|
||||
return com.gitpitch.controllers.routes.PitchController
|
||||
.slideshow(_pp.user,
|
||||
_pp.repo,
|
||||
_pp.branch,
|
||||
_pp.grs,
|
||||
_pp.theme,
|
||||
_pp.pitchme,
|
||||
_pp.notes, null, null, null).absoluteURL(isEncrypted(),
|
||||
hostname());
|
||||
}
|
||||
|
||||
/*
|
||||
* Return URL to oEmbed discovery link for slideshow.
|
||||
*/
|
||||
public String oembed(String url, String format) {
|
||||
|
||||
log.debug("oembed: [ {}, {} ]", url, format);
|
||||
return com.gitpitch.controllers.routes.PitchController.oembed(url,
|
||||
format, null, null, null, null, null)
|
||||
.absoluteURL(isEncrypted(), hostname());
|
||||
}
|
||||
|
||||
/*
|
||||
* Return relative URL to PITCHME.md markdown.
|
||||
*/
|
||||
public String markdownURL() {
|
||||
return _markdownURL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return https://{grs}/{user}.
|
||||
*/
|
||||
public String orgHub() {
|
||||
return _orgHub;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return https://{grs}/{user}/{repo}.
|
||||
*/
|
||||
public String repoHub() {
|
||||
return _repoHub;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return https://{grs}/{user}/{repo}/tree/{branch}
|
||||
*/
|
||||
public String branchHub(PitchParams pp) {
|
||||
|
||||
String branchHub = "#";
|
||||
|
||||
switch(pp.grs) {
|
||||
case GRS_GITHUB:
|
||||
case GRS_GITLAB:
|
||||
case GRS_GITBUCKET:
|
||||
branchHub = _repoHub + GIT_TREE + pp.branch;
|
||||
break;
|
||||
case GRS_BITBUCKET:
|
||||
branchHub = _repoHub + GIT_SRC + pp.branch;
|
||||
break;
|
||||
case GRS_GITEA:
|
||||
branchHub = _repoHub + GIT_SRC_BRANCH + pp.branch;
|
||||
break;
|
||||
case GRS_GOGS:
|
||||
branchHub = _repoHub + GIT_SRC + pp.branch;
|
||||
break;
|
||||
}
|
||||
return branchHub;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return https://{grs}/{user}/{repo}/blob/{branch}/{pitchme}
|
||||
*/
|
||||
public String pitchHub(PitchParams pp) {
|
||||
|
||||
String pitchPath =
|
||||
(pp.pitchme != null) ? (pp.branch + SLASH + pp.pitchme) : pp.branch;
|
||||
String pitchHub = "#";
|
||||
|
||||
switch(pp.grs) {
|
||||
case GRS_GITHUB:
|
||||
case GRS_GITLAB:
|
||||
case GRS_GITBUCKET:
|
||||
pitchHub = _repoHub + GIT_BLOB + pitchPath + DEFAULT_PITCHME;
|
||||
break;
|
||||
case GRS_BITBUCKET:
|
||||
pitchHub = _repoHub + GIT_SRC + pitchPath + DEFAULT_PITCHME;
|
||||
break;
|
||||
case GRS_GITEA:
|
||||
pitchHub = _repoHub + GIT_SRC_BRANCH + pitchPath + DEFAULT_PITCHME;
|
||||
break;
|
||||
case GRS_GOGS:
|
||||
pitchHub = _repoHub + GIT_SRC + pitchPath + DEFAULT_PITCHME;
|
||||
break;
|
||||
}
|
||||
return pitchHub;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return https://github.com/{user}/{repo}/stargazers.
|
||||
*/
|
||||
public String starHub() {
|
||||
return _starHub;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return https://github.com/{user}/{repo}/network.
|
||||
*/
|
||||
public String forkHub() {
|
||||
return _forkHub;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return number of Git repository stargazers.
|
||||
*/
|
||||
public int stargazers() {
|
||||
return (_grm != null) ? _grm.stargazers() : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return number of Git repository forks.
|
||||
*/
|
||||
public int forks() {
|
||||
return (_grm != null) ? _grm.forks() : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return Git repository language.
|
||||
*/
|
||||
public String repoLang() {
|
||||
|
||||
String repoLang = null;
|
||||
|
||||
if(_grm != null) {
|
||||
if(_grm.lang() != null && _grm.lang().length() > 0) {
|
||||
repoLang = _grm.lang();
|
||||
}
|
||||
}
|
||||
return repoLang;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if ViewModel represents a valid
|
||||
* repository on Git.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return _grm != null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the "best fit" repo language or branch
|
||||
* name when rendering the presentation.
|
||||
*/
|
||||
public String displayLangOrBranch() {
|
||||
|
||||
if (!isValid()) {
|
||||
return _pp.branch;
|
||||
} else if (isMaster() && repoLang() != null) {
|
||||
return repoLang();
|
||||
} else {
|
||||
return _pp.branch;
|
||||
}
|
||||
}
|
||||
|
||||
public String pageLink() {
|
||||
return pageLink(false);
|
||||
}
|
||||
|
||||
public String pageLink(boolean absolute) {
|
||||
return pageLink(absolute, null);
|
||||
}
|
||||
|
||||
public String pageLink(boolean absolute, String grs) {
|
||||
|
||||
grs = (grs != null) ? grs : _pp.grs;
|
||||
|
||||
if (absolute)
|
||||
return com.gitpitch.controllers.routes.PitchController
|
||||
.slideshow(_pp.user,
|
||||
_pp.repo,
|
||||
_pp.branch,
|
||||
grs,
|
||||
_pp.theme,
|
||||
_pp.pitchme,
|
||||
_pp.notes,
|
||||
null, null, null)
|
||||
.absoluteURL(isEncrypted(),
|
||||
hostname());
|
||||
else
|
||||
return com.gitpitch.controllers.routes.PitchController
|
||||
.slideshow(_pp.user,
|
||||
_pp.repo,
|
||||
_pp.branch,
|
||||
grs,
|
||||
_pp.theme,
|
||||
_pp.pitchme,
|
||||
_pp.notes, null, null, null).toString();
|
||||
}
|
||||
|
||||
public String pageLinkWithTheme(String theme) {
|
||||
|
||||
return com.gitpitch.controllers.routes.PitchController
|
||||
.slideshow(_pp.user,
|
||||
_pp.repo,
|
||||
_pp.branch,
|
||||
_pp.grs,
|
||||
theme,
|
||||
_pp.pitchme,
|
||||
_pp.notes,
|
||||
null, null, null).toString();
|
||||
}
|
||||
|
||||
public String printLink() {
|
||||
|
||||
return com.gitpitch.controllers.routes.PitchController.print(_pp.grs,
|
||||
_pp.user,
|
||||
_pp.repo,
|
||||
_pp.branch,
|
||||
_pp.theme,
|
||||
_pp.pitchme,
|
||||
_pp.notes).toString();
|
||||
}
|
||||
|
||||
public String printBrowserLink() {
|
||||
|
||||
return com.gitpitch.controllers.routes.PitchController
|
||||
.slideshow(_pp.user,
|
||||
_pp.repo,
|
||||
_pp.branch,
|
||||
_pp.grs,
|
||||
_pp.theme,
|
||||
_pp.pitchme,
|
||||
_pp.notes,
|
||||
null,
|
||||
"false",
|
||||
"true").toString();
|
||||
}
|
||||
|
||||
public String offlineLink() {
|
||||
|
||||
return com.gitpitch.controllers.routes.PitchController.offline(_pp.grs,
|
||||
_pp.user,
|
||||
_pp.repo,
|
||||
_pp.branch,
|
||||
_pp.theme,
|
||||
_pp.pitchme,
|
||||
_pp.notes).toString();
|
||||
}
|
||||
|
||||
public String twitterLink() {
|
||||
|
||||
return new StringBuffer("http://twitter.com/share?text=")
|
||||
.append("GitPitch presentation...")
|
||||
.append("&url=")
|
||||
.append(pageLink(true, null))
|
||||
.append("&hashtags=gitpitch")
|
||||
.toString();
|
||||
|
||||
}
|
||||
|
||||
public String linkedInLink() {
|
||||
|
||||
return new StringBuffer("https://www.linkedin.com/shareArticle")
|
||||
.append("?source=gitpitch")
|
||||
.append("&mini=true")
|
||||
.append("&summary=GitPitch%20presentation...")
|
||||
.append("&title=GitPitch")
|
||||
.append("&url=")
|
||||
.append(pageLink(true, null))
|
||||
.toString();
|
||||
|
||||
}
|
||||
|
||||
public String pageEmbed() {
|
||||
|
||||
return new StringBuffer(EMBED_OPEN)
|
||||
.append(pageLink(true))
|
||||
.append(EMBED_CLOSE)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String pageBadge() {
|
||||
|
||||
return new StringBuffer(BADGE_OPEN)
|
||||
.append(pageLink(true))
|
||||
.append(BADGE_CLOSE)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String getGRS(PitchParams pp) {
|
||||
String grsName = null;
|
||||
for(GRS grs : _grsServices) {
|
||||
if(grs.getType().equals(pp.grs)) {
|
||||
grsName = grs.getName();
|
||||
}
|
||||
}
|
||||
return grsName;
|
||||
}
|
||||
|
||||
public List<GRS> listGRS() {
|
||||
return _grsServices;
|
||||
}
|
||||
|
||||
public String getGRSIcon(PitchParams pp) {
|
||||
|
||||
String icon = GIT_DEFAULT_ICON;
|
||||
|
||||
switch(pp.grs) {
|
||||
|
||||
case "github":
|
||||
icon = GITHUB_ICON;
|
||||
break;
|
||||
case "gitlab":
|
||||
icon = GITLAB_ICON;
|
||||
break;
|
||||
case "bitbucket":
|
||||
icon = BITBUCKET_ICON;
|
||||
break;
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
public List<String> listThemes() {
|
||||
List<String> themesList =
|
||||
runtime.configStringList("gitpitch.revealjs.themes");
|
||||
if(themesList == null || themesList.isEmpty()) {
|
||||
themesList = DEPLOY_THEMES;
|
||||
}
|
||||
return themesList;
|
||||
}
|
||||
|
||||
public String pageDescription() {
|
||||
if(model() != null && model().description() != null) {
|
||||
return model().description();
|
||||
} else {
|
||||
return AS_DESCR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return string representation of ViewModel.
|
||||
*/
|
||||
public String toString() {
|
||||
return _slideshowURL;
|
||||
}
|
||||
|
||||
private boolean isEncrypted() {
|
||||
return runtime.configBool("gitpitch.https");
|
||||
}
|
||||
|
||||
private String hostname() {
|
||||
return runtime.config("gitpitch.hostname");
|
||||
}
|
||||
|
||||
private static final String GIT_MASTER = "master";
|
||||
private static final String GIT_TREE = "/tree/";
|
||||
private static final String GIT_BLOB = "/blob/";
|
||||
private static final String GIT_SRC = "/src/";
|
||||
private static final String GIT_SRC_BRANCH = "/src/branch/";
|
||||
private static final String CSS = ".css";
|
||||
private static final String MARKDOWN = "/pitchme/markdown/";
|
||||
private static final String SLASH = "/";
|
||||
private static final String QMARK_BRANCH = "?b=";
|
||||
private static final String QMARK_THEME = "&t=";
|
||||
private static final String HTTP_HASH = "#";
|
||||
private static final String EMBED_OPEN =
|
||||
"<iframe width='770' height='515' src='";
|
||||
private static final String EMBED_CLOSE =
|
||||
"' frameborder='0' allowfullscreen></iframe>";
|
||||
private static final String BADGE_OPEN =
|
||||
"[![GitPitch](https://gitpitch.com/assets/badge.svg)](";
|
||||
private static final String BADGE_CLOSE = ")";
|
||||
private static final String PITCHME = "PITCHME.md";
|
||||
private static final String DEFAULT_PITCHME = "/PITCHME.md";
|
||||
private static final String DEFAULT_THEME = "white";
|
||||
private static final List<String> THEMES = Arrays.asList(DEFAULT_THEME,
|
||||
"beige", "black", "moon", "night", "sky", "white");
|
||||
|
||||
private static final String GRS_GITHUB_COM = "https://github.com/";
|
||||
private static final String GRS_GITHUB_STARS = "stargazers";
|
||||
private static final String GRS_GITHUB_FORKS = "network";
|
||||
private static final String GRS_GITLAB_STARS = "activity";
|
||||
private static final String GRS_GITLAB_FORKS = "graphs/";
|
||||
private static final String GRS_BITBUCKET_STARS = "commits/all";
|
||||
private static final String GRS_BITBUCKET_FORKS = "branches";
|
||||
|
||||
private static final String GITHUB_ICON =
|
||||
"<span class='octicon octicon-mark-github'></span>";
|
||||
private static final String GITLAB_ICON =
|
||||
"<i class='fa fa-gitlab' aria-hidden='true'></i>";
|
||||
private static final String BITBUCKET_ICON =
|
||||
"<i class='fa fa-bitbucket' aria-hidden='true'></i>";
|
||||
private static final String GIT_DEFAULT_ICON =
|
||||
"<i class='fa fa-git-square' aria-hidden='true'></i>";
|
||||
|
||||
private static final String GRS_GITHUB = "github";
|
||||
private static final String GRS_GITLAB = "gitlab";
|
||||
private static final String GRS_BITBUCKET = "bitbucket";
|
||||
private static final String GRS_GITBUCKET = "gitbucket";
|
||||
private static final String GRS_GITEA = "gitea";
|
||||
private static final String GRS_GOGS = "gogs";
|
||||
|
||||
private static final String AS_DESCR =
|
||||
"Markdown Presentation powered by GitPitch.";
|
||||
|
||||
private static final List<String> DEPLOY_THEMES =
|
||||
Arrays.asList("black", "moon", "night", "beige", "sky", "white");
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.utils;
|
||||
|
||||
import com.gitpitch.git.GRSService;
|
||||
import com.gitpitch.models.SlideshowModel;
|
||||
import com.gitpitch.services.DiskService;
|
||||
import play.Logger;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
/*
|
||||
* Rendering model for PITCHME.md markdown.
|
||||
*/
|
||||
public class MarkdownRenderer {
|
||||
|
||||
private final Logger.ALogger log = Logger.of(this.getClass());
|
||||
|
||||
private final PitchParams _pp;
|
||||
private final Optional<SlideshowModel> _ssm;
|
||||
private GRSService grsService;
|
||||
private DiskService diskService;
|
||||
|
||||
private MarkdownRenderer(PitchParams pp,
|
||||
Optional<SlideshowModel> ssm,
|
||||
GRSService grsService,
|
||||
DiskService diskService) {
|
||||
|
||||
this._pp = pp;
|
||||
this._ssm = ssm;
|
||||
this.grsService = grsService;
|
||||
this.diskService = diskService;
|
||||
}
|
||||
|
||||
public static MarkdownRenderer build(PitchParams pp,
|
||||
Optional<SlideshowModel> ssm,
|
||||
GRSService grsService,
|
||||
DiskService diskService) {
|
||||
|
||||
return new MarkdownRenderer(pp, ssm, grsService, diskService);
|
||||
}
|
||||
|
||||
public PitchParams pp() {
|
||||
return _pp;
|
||||
}
|
||||
|
||||
public Optional<SlideshowModel> ssm() {
|
||||
return _ssm;
|
||||
}
|
||||
|
||||
public String gitRawBase() {
|
||||
return grsService.raw(_pp);
|
||||
}
|
||||
|
||||
public Path filePath(String filename) {
|
||||
return diskService.asPath(_pp, filename);
|
||||
}
|
||||
|
||||
public boolean hasLogo() {
|
||||
|
||||
if (_ssm.isPresent()) {
|
||||
|
||||
SlideshowModel model = _ssm.get();
|
||||
log.debug("hasLogo: ssm found, hasLogo={}", model.hasLogo());
|
||||
return model.hasLogo();
|
||||
|
||||
} else {
|
||||
log.debug("hasLogo: ssm not found, so no logo.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String fetchLogo() {
|
||||
|
||||
if (_ssm.isPresent()) {
|
||||
|
||||
SlideshowModel model = _ssm.get();
|
||||
return model.fetchLogo();
|
||||
|
||||
} else {
|
||||
return "#";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean hasLogoPosition() {
|
||||
|
||||
if (_ssm.isPresent()) {
|
||||
|
||||
SlideshowModel model = _ssm.get();
|
||||
log.debug("hasLogoPosition: ssm found, hasLogoPosition={}", model.hasLogoPosition());
|
||||
return model.hasLogoPosition();
|
||||
|
||||
} else {
|
||||
log.debug("hasLogoPosition: ssm not found, so no logoPosition.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String fetchLogoPosition() {
|
||||
|
||||
if (_ssm.isPresent()) {
|
||||
|
||||
SlideshowModel model = _ssm.get();
|
||||
return model.fetchLogoPosition();
|
||||
} else {
|
||||
return "#";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.utils;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* GitPitch URL utility parser.
|
||||
*/
|
||||
public class PitchLink {
|
||||
|
||||
public String url;
|
||||
public String user = UNDEFINED;
|
||||
public String repo = UNDEFINED;
|
||||
public String branch = DEFAULT_BRANCH;
|
||||
public String grs = DEFAULT_GRS;
|
||||
|
||||
private PitchLink(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
private PitchLink(String url,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String grs) {
|
||||
|
||||
this.url = url;
|
||||
this.user = user;
|
||||
this.repo = repo;
|
||||
this.branch = branch;
|
||||
this.grs = grs;
|
||||
}
|
||||
|
||||
public static PitchLink build(String url) {
|
||||
try {
|
||||
URL urlo = new URL(url);
|
||||
String path = urlo.getPath();
|
||||
String[] paths = path.split(SLASH);
|
||||
String uPath = paths[1];
|
||||
String rPath = paths[2];
|
||||
String bPath = (paths.length == 4) ? paths[3] : DEFAULT_BRANCH;
|
||||
String query = urlo.getQuery();
|
||||
String gPath = DelimParams.build(query).get(GRS, DEFAULT_GRS);
|
||||
return new PitchLink(url, uPath, rPath, bPath, gPath);
|
||||
} catch(Exception ex) {
|
||||
return new PitchLink(url);
|
||||
}
|
||||
}
|
||||
|
||||
private final static String DEFAULT_BRANCH = "master";
|
||||
private final static String DEFAULT_GRS = "github";
|
||||
private final static String UNDEFINED = "undefined";
|
||||
private final static String GRS = "grs";
|
||||
private final static String SLASH = "/";
|
||||
|
||||
}
|
|
@ -1,269 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* GitPitch API Parameters Command Object.
|
||||
*/
|
||||
public class PitchParams {
|
||||
|
||||
public String user;
|
||||
public String repo;
|
||||
public String branch;
|
||||
public String theme;
|
||||
public String notes;
|
||||
public String grs;
|
||||
public String pitchme;
|
||||
|
||||
private PitchParams(String grs,
|
||||
String user,
|
||||
String repo) {
|
||||
|
||||
this(grs, user, repo, null);
|
||||
}
|
||||
private PitchParams(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch) {
|
||||
|
||||
this(grs, user, repo, branch, null);
|
||||
}
|
||||
private PitchParams(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String theme) {
|
||||
this(grs, user, repo, branch, theme, null);
|
||||
}
|
||||
private PitchParams(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String theme,
|
||||
String pitchme) {
|
||||
|
||||
this(grs, user, repo, branch, theme, pitchme, null);
|
||||
}
|
||||
private PitchParams(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String theme,
|
||||
String pitchme,
|
||||
String notes) {
|
||||
|
||||
this.grs = grs;
|
||||
|
||||
this.user = user;
|
||||
this.repo = repo;
|
||||
this.branch = (branch != null) ? branch : DEFAULT_BRANCH;
|
||||
|
||||
if (DEFAULT_THEMES.contains(theme))
|
||||
this.theme = theme;
|
||||
else
|
||||
this.theme = DEFAULT_THEME;
|
||||
|
||||
this.pitchme = pitchme;
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
public static PitchParams build(String grs,
|
||||
String user,
|
||||
String repo) {
|
||||
|
||||
return new PitchParams(grs, user, repo);
|
||||
}
|
||||
|
||||
public static PitchParams build(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch) {
|
||||
|
||||
return new PitchParams(grs, user, repo, branch);
|
||||
}
|
||||
|
||||
public static PitchParams build(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String theme) {
|
||||
|
||||
return new PitchParams(grs, user, repo, branch, theme);
|
||||
}
|
||||
|
||||
public static PitchParams build(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String theme,
|
||||
String pitchme) {
|
||||
|
||||
return new PitchParams(grs, user, repo, branch, theme, pitchme);
|
||||
}
|
||||
|
||||
public static PitchParams build(String grs,
|
||||
String user,
|
||||
String repo,
|
||||
String branch,
|
||||
String theme,
|
||||
String pitchme,
|
||||
String notes) {
|
||||
|
||||
return new PitchParams(grs, user, repo, branch, theme, pitchme, notes);
|
||||
}
|
||||
|
||||
public static boolean isDarkTheme(String theme) {
|
||||
return DARK_THEMES.contains(theme);
|
||||
}
|
||||
|
||||
public static boolean isLightTheme(String theme) {
|
||||
return LIGHT_THEMES.contains(theme);
|
||||
}
|
||||
|
||||
public static String fetchThemeCSS(String theme) {
|
||||
return new StringBuffer(theme).append(DOT_CSS)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String MD() {
|
||||
return (pitchme != null) ?
|
||||
pitchme + SLASH + PITCHME_MD : PITCHME_MD;
|
||||
}
|
||||
|
||||
public String YAML() {
|
||||
return (pitchme != null) ?
|
||||
pitchme + SLASH + PITCHME_YAML : PITCHME_YAML;
|
||||
}
|
||||
|
||||
public String PDF() {
|
||||
return (pitchme != null) ?
|
||||
pitchme + SLASH + PITCHME_PDF : PITCHME_PDF;
|
||||
}
|
||||
|
||||
public boolean isMaster() {
|
||||
return GIT_MASTER.equals(this.branch);
|
||||
}
|
||||
|
||||
public boolean isLongLived() {
|
||||
return USER_GITPITCH.equals(this.user);
|
||||
}
|
||||
|
||||
public boolean darkTheme() {
|
||||
return DARK_THEMES.contains(this.theme);
|
||||
}
|
||||
|
||||
public boolean lightTheme() {
|
||||
return LIGHT_THEMES.contains(this.theme);
|
||||
}
|
||||
|
||||
public String pretty() {
|
||||
|
||||
StringBuffer pretty =
|
||||
new StringBuffer(SLASH).append(grs)
|
||||
.append(SLASH)
|
||||
.append(user)
|
||||
.append(SLASH)
|
||||
.append(repo);
|
||||
|
||||
if(!branch.equals(GIT_MASTER)) {
|
||||
pretty.append(SLASH).append(branch);
|
||||
}
|
||||
|
||||
return pretty.toString();
|
||||
}
|
||||
|
||||
public String atPretty() {
|
||||
String pretty = pretty().substring(1);
|
||||
return new StringBuffer(AT).append(pretty).toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new StringBuffer(SLASH).append(grs)
|
||||
.append(SLASH)
|
||||
.append(user)
|
||||
.append(SLASH)
|
||||
.append(repo)
|
||||
.append(SLASH)
|
||||
.append(branch)
|
||||
.append(" [ ")
|
||||
.append(theme)
|
||||
.append(", ")
|
||||
.append(pitchme)
|
||||
.append(" ]")
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String asLogo() {
|
||||
return new StringBuffer(user).append(SPACED_SLASH)
|
||||
.append(repo)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String asTitle() {
|
||||
return new StringBuffer("[ GitPitch ] ")
|
||||
.append(user)
|
||||
.append(SLASH)
|
||||
.append(repo)
|
||||
.append(SLASH)
|
||||
.append(branch)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public boolean isValidTheme(String themeName) {
|
||||
return DEFAULT_THEMES.contains(themeName);
|
||||
}
|
||||
|
||||
public boolean isValidPosition(String logoPosition) {
|
||||
return LOGO_POSITIONS.contains(logoPosition);
|
||||
}
|
||||
|
||||
public static final String PITCHME_MD = "PITCHME.md";
|
||||
public static final String PITCHME_YAML = "PITCHME.yaml";
|
||||
public static final String PITCHME_PDF = "PITCHME.pdf";
|
||||
public static final String DEFAULT_THEME = "white";
|
||||
public static final String DEFAULT_THEME_CSS = "white.css";
|
||||
public static final String DEFAULT_LOGO_POSITION = "top-left";
|
||||
private static final List<String> LOGO_POSITIONS =
|
||||
Arrays.asList("top-left", "top-right", "bottom-left", "bottom-right");
|
||||
private static final List<String> DARK_THEMES =
|
||||
Arrays.asList("black", "moon", "night");
|
||||
private static final List<String> LIGHT_THEMES =
|
||||
Arrays.asList("beige", "sky", "white");
|
||||
private static final List<String> DEFAULT_THEMES =
|
||||
Arrays.asList("black", "moon", "night", "beige", "sky", "white");
|
||||
private static final String DOT_CSS = ".css";
|
||||
private final String USER_GITPITCH = "gitpitch";
|
||||
private final String GIT_MASTER = "master";
|
||||
private final String DEFAULT_BRANCH = "master";
|
||||
private final String PARAM_BRANCH = "?b=";
|
||||
private final String PARAM_THEME = "&t=";
|
||||
private final String PARAM_NOTES = "&n=";
|
||||
private final String SLASH = "/";
|
||||
private final String SPACED_SLASH = " / ";
|
||||
private final String AT = "@ ";
|
||||
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.utils;
|
||||
|
||||
import com.gitpitch.git.GRS;
|
||||
import com.gitpitch.utils.PitchParams;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/*
|
||||
* GitHub RFE issue support utility.
|
||||
*/
|
||||
public final class RFE {
|
||||
|
||||
/*
|
||||
* Build message that offers the user a
|
||||
* chance to submit a Feature Request (Issue)
|
||||
* against the repo identified by PitchParams.
|
||||
*/
|
||||
public static String master(PitchParams pp, GRS grs) {
|
||||
|
||||
String newIssue = grs.getSite() +
|
||||
pp.user + "/" + pp.repo + "/issues/new";
|
||||
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("<span style=\"font-size:1.1em\">Presentation 404</span><br><br>")
|
||||
.append("\n\n")
|
||||
.append("<span style=\"font-size:0.9em\">")
|
||||
.append("PITCHME.md not found in repo on ")
|
||||
.append(grs.getName())
|
||||
.append(".</span>");
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static String branch(PitchParams pp, GRS grs) {
|
||||
|
||||
return new StringBuffer("<span style=\"font-size:1.1em\">")
|
||||
.append("Presentation 404</span><br><br>")
|
||||
.append("\n\n")
|
||||
.append("<span style=\"font-size:0.9em\">")
|
||||
.append("PITCHME.md not found in branch on ")
|
||||
.append(grs.getName())
|
||||
.append(".</span>")
|
||||
.toString();
|
||||
}
|
||||
}
|
|
@ -1,498 +0,0 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016 David Russell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.gitpitch.utils;
|
||||
|
||||
import com.gitpitch.git.GRSService;
|
||||
import com.gitpitch.services.DiskService;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import play.Logger;
|
||||
import play.Logger.ALogger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* PITCHME.yaml options utility.
|
||||
*/
|
||||
public final class YAMLOptions {
|
||||
|
||||
private final static Logger.ALogger log =
|
||||
Logger.of("com.gitpitch.utils.YAMLOptions");
|
||||
|
||||
private final Map<String, String> _yProps;
|
||||
private final GRSService grsService;
|
||||
|
||||
private YAMLOptions(Map<String, String> yProps,
|
||||
GRSService grsService) {
|
||||
this._yProps = yProps;
|
||||
this.grsService = grsService;
|
||||
}
|
||||
|
||||
public static YAMLOptions build(PitchParams pp,
|
||||
GRSService grsService,
|
||||
DiskService diskService) {
|
||||
|
||||
YAMLOptions yOpts = null;
|
||||
|
||||
try {
|
||||
|
||||
/*
|
||||
* Instantiate YAML parser.
|
||||
*/
|
||||
Yaml yaml = new Yaml();
|
||||
|
||||
/*
|
||||
* Build path to PITCHME_YAML on disk.
|
||||
*/
|
||||
Path yPath = diskService.asPath(pp, PITCHME_YAML);
|
||||
File yFile = yPath.toFile();
|
||||
|
||||
if (yFile.exists()) {
|
||||
|
||||
/*
|
||||
* Use YAML parser to transform YAML properties to Map.
|
||||
*/
|
||||
Map<String, String> yProps =
|
||||
(Map<String, String>) yaml.load(new FileReader(yPath.toFile()));
|
||||
|
||||
/*
|
||||
* Handle PITCHME.yaml empty file without properites.
|
||||
*/
|
||||
if (yProps == null) {
|
||||
yProps = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
log.debug("build: pp={}, props={}", pp, yProps);
|
||||
|
||||
yOpts = new YAMLOptions(yProps, grsService);
|
||||
} else {
|
||||
log.debug("build: pp={}, yaml not found={}", yFile);
|
||||
}
|
||||
|
||||
} catch (Exception yex) {
|
||||
|
||||
log.warn("build: pp={}, parsing YAML ex={}", pp, yex);
|
||||
|
||||
} finally {
|
||||
|
||||
return yOpts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean fixedTheme(PitchParams pp) {
|
||||
return _yProps.get(THEME_OPTION) != null;
|
||||
}
|
||||
|
||||
public String fetchTheme(PitchParams pp) {
|
||||
|
||||
String theme = _yProps.get(THEME_OPTION);
|
||||
return pp.isValidTheme(theme) ? theme : pp.theme;
|
||||
}
|
||||
|
||||
public String fetchLayout(PitchParams pp) {
|
||||
String layout = _yProps.get(LAYOUT_OPTION);
|
||||
return isValidLayout(layout) ? layout : DEFAULT_LAYOUT;
|
||||
}
|
||||
|
||||
private boolean isValidLayout(String layoutName) {
|
||||
return DEFAULT_LAYOUTS.contains(layoutName);
|
||||
}
|
||||
|
||||
public boolean isLeftLayout(PitchParams pp) {
|
||||
return fetchLayout(pp).contains(LEFT);
|
||||
}
|
||||
|
||||
public boolean isRightLayout(PitchParams pp) {
|
||||
return fetchLayout(pp).contains(RIGHT);
|
||||
}
|
||||
|
||||
public boolean isTopLayout(PitchParams pp) {
|
||||
return fetchLayout(pp).contains(TOP);
|
||||
}
|
||||
|
||||
public String fetchThemeCSS(PitchParams pp) {
|
||||
|
||||
return new StringBuffer(fetchTheme(pp)).append(DOT_CSS)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public boolean hasThemeOverride(PitchParams pp) {
|
||||
return (_yProps.get(THEME_OVERRIDE_OPTION) != null);
|
||||
}
|
||||
|
||||
public String fetchThemeOverride(PitchParams pp) {
|
||||
|
||||
String overridePath = _yProps.get(THEME_OVERRIDE_OPTION);
|
||||
|
||||
if (isAbsolute(overridePath)) {
|
||||
return overridePath;
|
||||
} else {
|
||||
return grsService.raw(pp, overridePath);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasLogo() {
|
||||
return (_yProps.get(LOGO_OPTION) != null);
|
||||
}
|
||||
|
||||
public String fetchLogo(PitchParams pp) {
|
||||
|
||||
String logoPath = _yProps.get(LOGO_OPTION);
|
||||
|
||||
if (isAbsolute(logoPath)) {
|
||||
return logoPath;
|
||||
} else {
|
||||
return grsService.raw(pp, logoPath);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasLogoPosition() {
|
||||
return (_yProps.get(LOGO_POSITION_OPTION) != null);
|
||||
}
|
||||
|
||||
public String fetchLogoPosition(PitchParams pp) {
|
||||
|
||||
String logoPosition = _yProps.get(LOGO_POSITION_OPTION);
|
||||
return pp.isValidPosition(logoPosition) ? logoPosition : pp.DEFAULT_LOGO_POSITION;
|
||||
}
|
||||
|
||||
public boolean hasImageBg() {
|
||||
return (_yProps.get(IMAGE_BG_OPTION) != null);
|
||||
}
|
||||
|
||||
public String fetchImageBg(PitchParams pp) {
|
||||
|
||||
String imgBgPath = _yProps.get(IMAGE_BG_OPTION);
|
||||
|
||||
if (isAbsolute(imgBgPath)) {
|
||||
return imgBgPath;
|
||||
} else {
|
||||
return grsService.raw(pp, imgBgPath);
|
||||
}
|
||||
}
|
||||
|
||||
public String fetchImageBgSize(PitchParams pp) {
|
||||
String bgSize = _yProps.get(IMAGE_BG_SIZE_OPTION);
|
||||
if (bgSize == null) {
|
||||
return DEFAULT_BG_SIZE;
|
||||
} else {
|
||||
return bgSize;
|
||||
}
|
||||
}
|
||||
|
||||
public String fetchImageBgColor(PitchParams pp) {
|
||||
String bgColor = _yProps.get(IMAGE_BG_COLOR_OPTION);
|
||||
if (bgColor == null) {
|
||||
return DEFAULT_BG_COLOR;
|
||||
} else {
|
||||
return bgColor;
|
||||
}
|
||||
}
|
||||
|
||||
public String fetchImageBgPosition(PitchParams pp) {
|
||||
String bgPosition = _yProps.get(IMAGE_BG_POSITION_OPTION);
|
||||
if (bgPosition == null) {
|
||||
return DEFAULT_BG_POSITION;
|
||||
} else {
|
||||
return bgPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public String fetchImageBgRepeat(PitchParams pp) {
|
||||
String bgRepeat = _yProps.get(IMAGE_BG_REPEAT_OPTION);
|
||||
if (bgRepeat == null) {
|
||||
return DEFAULT_BG_REPEAT;
|
||||
} else {
|
||||
return bgRepeat;
|
||||
}
|
||||
}
|
||||
|
||||
public String fetchTransition(PitchParams pp) {
|
||||
|
||||
String transition = _yProps.get(TRANSITION_OPTION);
|
||||
|
||||
if (TRANSITIONS.contains(transition))
|
||||
return transition;
|
||||
else
|
||||
return DEFAULT_TRANSITION;
|
||||
}
|
||||
|
||||
public String fetchControlsLayout(PitchParams pp) {
|
||||
|
||||
String layout = _yProps.get(CONTROLS_LAYOUT_OPTION);
|
||||
|
||||
if (CONTROL_LAYOUTS.contains(layout))
|
||||
return layout;
|
||||
else
|
||||
return DEFAULT_CONTROLS_LAYOUT;
|
||||
}
|
||||
|
||||
public Integer fetchAutoSlide(PitchParams pp) {
|
||||
return fetchIntegerOption(pp, AUTOSLIDE_OPTION);
|
||||
}
|
||||
|
||||
public Boolean fetchVerticalCenter(PitchParams pp) {
|
||||
return fetchBooleanOption(pp, VERTICAL_CENTER, true);
|
||||
}
|
||||
|
||||
public Boolean fetchLoop(PitchParams pp) {
|
||||
return fetchBooleanOption(pp, LOOP_OPTION);
|
||||
}
|
||||
|
||||
public Boolean fetchRemoteControl(PitchParams pp) {
|
||||
return fetchBooleanOption(pp, REMOTE_CONTROL_OPTION);
|
||||
}
|
||||
|
||||
public Integer fetchRemoteControlPrevKey(PitchParams pp) {
|
||||
return fetchIntegerOption(pp, REMOTE_CONTROL_PREVKEY_OPTION);
|
||||
}
|
||||
|
||||
public Integer fetchRemoteControlNextKey(PitchParams pp) {
|
||||
return fetchIntegerOption(pp, REMOTE_CONTROL_NEXTKEY_OPTION);
|
||||
}
|
||||
|
||||
public Boolean fetchRTL(PitchParams pp) {
|
||||
return fetchBooleanOption(pp, RTL_OPTION);
|
||||
}
|
||||
|
||||
public Boolean fetchShuffle(PitchParams pp) {
|
||||
return fetchBooleanOption(pp, SHUFFLE_OPTION);
|
||||
}
|
||||
|
||||
public Boolean fetchMouseWheel(PitchParams pp) {
|
||||
return fetchBooleanOption(pp, MOUSE_WHEEL_OPTION);
|
||||
}
|
||||
|
||||
public Boolean fetchCharts(PitchParams pp) {
|
||||
return fetchBooleanOption(pp, CHARTS_OPTION);
|
||||
}
|
||||
|
||||
public Boolean mathEnabled(PitchParams pp) {
|
||||
String mathjax = _yProps.get(MATHJAX_OPTION);
|
||||
return (mathjax != null);
|
||||
}
|
||||
|
||||
public Boolean fetchHistory(PitchParams pp) {
|
||||
return fetchBooleanOption(pp, HISTORY_OPTION, true);
|
||||
}
|
||||
|
||||
public Boolean fetchSlideNumber(PitchParams pp) {
|
||||
return fetchBooleanOption(pp, SLIDE_NUMBER_OPTION);
|
||||
}
|
||||
|
||||
public String mathConfig(PitchParams pp) {
|
||||
return mathEnabled(pp) ?
|
||||
_yProps.get(MATHJAX_OPTION) : MATHJAX_DEFAULT;
|
||||
}
|
||||
|
||||
public Boolean highlightEnabled(PitchParams pp) {
|
||||
return (_yProps.get(HIGHLIGHT_OPTION) != null) ? true : false;
|
||||
}
|
||||
|
||||
public String fetchHighlight(PitchParams pp) {
|
||||
return highlightEnabled(pp) ?
|
||||
(_yProps.get(HIGHLIGHT_OPTION) + ".css") :
|
||||
defaultHighlight(pp);
|
||||
}
|
||||
|
||||
public boolean hasFootnote(PitchParams pp) {
|
||||
return _yProps.get(FOOTNOTE_OPTION) != null;
|
||||
}
|
||||
|
||||
public String fetchFootnote(PitchParams pp) {
|
||||
return _yProps.get(FOOTNOTE_OPTION);
|
||||
}
|
||||
|
||||
public boolean hasGAToken(PitchParams pp) {
|
||||
return (_yProps.get(GATOKEN_OPTION) != null);
|
||||
}
|
||||
|
||||
public String fetchGAToken(PitchParams pp) {
|
||||
return _yProps.get(GATOKEN_OPTION);
|
||||
}
|
||||
|
||||
public boolean hasHorzDelim(PitchParams pp) {
|
||||
return _yProps.get(HSLIDE_DELIM) != null;
|
||||
}
|
||||
|
||||
public String fetchHorzDelim(PitchParams pp) {
|
||||
return _yProps.get(HSLIDE_DELIM);
|
||||
}
|
||||
|
||||
public String fetchHorzDelimRegExp(PitchParams pp) {
|
||||
return _yProps.get(HSLIDE_DELIM_REGEXP);
|
||||
}
|
||||
|
||||
public boolean hasVertDelim(PitchParams pp) {
|
||||
return _yProps.get(VSLIDE_DELIM) != null;
|
||||
}
|
||||
|
||||
public String fetchVertDelim(PitchParams pp) {
|
||||
return _yProps.get(VSLIDE_DELIM);
|
||||
}
|
||||
|
||||
public String fetchVertDelimRegExp(PitchParams pp) {
|
||||
return _yProps.get(VSLIDE_DELIM_REGEXP);
|
||||
}
|
||||
|
||||
public String fetchRevealVersion(PitchParams pp) {
|
||||
return _yProps.get(REVEALJS_VERSION);
|
||||
}
|
||||
|
||||
public Boolean published(PitchParams pp) {
|
||||
return fetchBooleanOption(pp, PUBLISHED_OPTION);
|
||||
}
|
||||
|
||||
public Boolean printFrags(PitchParams pp) {
|
||||
return fetchBooleanOption(pp, PRINT_FRAGS_OPTIONS);
|
||||
}
|
||||
|
||||
private Boolean fetchBooleanOption(PitchParams pp, String option) {
|
||||
return fetchBooleanOption(pp, option, false);
|
||||
}
|
||||
|
||||
private Boolean fetchBooleanOption(PitchParams pp,
|
||||
String option, boolean dflt) {
|
||||
|
||||
try {
|
||||
Object optionValue = _yProps.get(option);
|
||||
|
||||
if (optionValue instanceof Boolean)
|
||||
return (Boolean) optionValue;
|
||||
else if (optionValue instanceof String)
|
||||
return Boolean.parseBoolean((String) optionValue);
|
||||
else
|
||||
return dflt;
|
||||
|
||||
} catch (Exception bex) {
|
||||
return dflt;
|
||||
}
|
||||
}
|
||||
|
||||
private Integer fetchIntegerOption(PitchParams pp, String option) {
|
||||
|
||||
try {
|
||||
Object optionValue = _yProps.get(option);
|
||||
|
||||
if (optionValue instanceof Integer)
|
||||
return (Integer) optionValue;
|
||||
else if (optionValue instanceof String)
|
||||
return Integer.parseInt((String) optionValue);
|
||||
else
|
||||
return 0;
|
||||
|
||||
} catch (NumberFormatException nfex) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private String defaultHighlight(PitchParams pp) {
|
||||
return PitchParams.isDarkTheme(fetchTheme(pp)) ?
|
||||
HIGHLIGHT_DARK_DEFAULT : HIGHLIGHT_LIGHT_DEFAULT;
|
||||
}
|
||||
|
||||
private boolean isAbsolute(String link) {
|
||||
return (link != null && link.startsWith(ABS_HTTP));
|
||||
}
|
||||
|
||||
public static final String PITCHME_YAML = "PITCHME.yaml";
|
||||
public static final String DEFAULT_BG_SIZE = "100% 100%";
|
||||
public static final String DEFAULT_BG_COLOR = " ";
|
||||
public static final String DEFAULT_BG_POSITION = "center";
|
||||
public static final String DEFAULT_BG_REPEAT = " ";
|
||||
public static final String DEFAULT_TRANSITION = "slide";
|
||||
public static final String DEFAULT_CONTROLS_LAYOUT = "bottom-right";
|
||||
public static final String EDGES_CONTROLS_LAYOUT = "edges";
|
||||
public static final String MATHJAX_DEFAULT = "TeX-MML-AM_CHTML";
|
||||
public static final String HIGHLIGHT_DARK_DEFAULT = "github-gist.css";
|
||||
public static final String HIGHLIGHT_LIGHT_DEFAULT = "hybrid.css";
|
||||
/*
|
||||
* PITCHME.yaml Supported Options.
|
||||
*/
|
||||
private static final String THEME_OPTION = "theme";
|
||||
private static final String THEME_OVERRIDE_OPTION = "theme-override";
|
||||
private static final String VERTICAL_CENTER = "vertical-center";
|
||||
private static final String LOGO_OPTION = "logo";
|
||||
private static final String LOGO_POSITION_OPTION = "logo-position";
|
||||
private static final String IMAGE_BG_OPTION = "background";
|
||||
private static final String IMAGE_BG_SIZE_OPTION = "background-size";
|
||||
private static final String IMAGE_BG_COLOR_OPTION = "background-color";
|
||||
private static final String IMAGE_BG_POSITION_OPTION = "background-position";
|
||||
private static final String IMAGE_BG_REPEAT_OPTION = "background-repeat";
|
||||
private static final String TRANSITION_OPTION = "transition";
|
||||
private static final String CONTROLS_LAYOUT_OPTION = "controls-layout";
|
||||
private static final String AUTOSLIDE_OPTION = "autoslide";
|
||||
private static final String LOOP_OPTION = "loop";
|
||||
private static final String REMOTE_CONTROL_OPTION = "remote-control";
|
||||
private static final String REMOTE_CONTROL_PREVKEY_OPTION =
|
||||
"remote-control-prevkey";
|
||||
private static final String REMOTE_CONTROL_NEXTKEY_OPTION =
|
||||
"remote-control-nextkey";
|
||||
private static final String RTL_OPTION = "rtl";
|
||||
private static final String SHUFFLE_OPTION = "shuffle";
|
||||
private static final String MOUSE_WHEEL_OPTION = "mousewheel";
|
||||
private static final String MATHJAX_OPTION = "mathjax";
|
||||
private static final String HIGHLIGHT_OPTION = "highlight";
|
||||
private static final String FOOTNOTE_OPTION = "footnote";
|
||||
private static final String GATOKEN_OPTION = "gatoken";
|
||||
private static final String CHARTS_OPTION = "charts";
|
||||
private static final String HISTORY_OPTION = "history";
|
||||
private static final String SLIDE_NUMBER_OPTION = "slide-number";
|
||||
private static final String REVEALJS_VERSION = "revealjs-version";
|
||||
private static final String PUBLISHED_OPTION = "published";
|
||||
private static final String PRINT_FRAGS_OPTIONS = "print-fragments";
|
||||
|
||||
private static final String HSLIDE_DELIM = "horz-delim";
|
||||
private static final String VSLIDE_DELIM = "vert-delim";
|
||||
private static final String HSLIDE_DELIM_REGEXP = "horz-delim-regexp";
|
||||
private static final String VSLIDE_DELIM_REGEXP = "vert-delim-regexp";
|
||||
|
||||
private static final List<String> TRANSITIONS =
|
||||
Arrays.asList("default", "none", "fade", "slide",
|
||||
"convex", "conconcave", "zoom");
|
||||
private static final List<String> CONTROL_LAYOUTS =
|
||||
Arrays.asList("bottom-left", "edges");
|
||||
private static final List<String> MATHJAX_CONFIGS =
|
||||
Arrays.asList("default",
|
||||
"TeX-MML-AM_CHTML", "TeX-MML-AM_HTMLorMML",
|
||||
"TeX-MML-AM_SVG", "TeX-AMS-MML_HTMLorMML",
|
||||
"TeX-AMS_CHTML", "TeX-AMS_SVG",
|
||||
"TeX-AMS_HTML", "MML_CHTML", "MML_SVG",
|
||||
"MML_HTMLorMML", "AM_CHTML", "AM_SVG",
|
||||
"AM_HTMLorMML", "TeX-AMS-MML_SVG",
|
||||
"Accessible");
|
||||
private static final String ABS_HTTP = "http";
|
||||
private static final String DOT_CSS = ".css";
|
||||
|
||||
private static final String LAYOUT_OPTION = "layout";
|
||||
private static final String DEFAULT_LAYOUT = "center";
|
||||
private static final List<String> DEFAULT_LAYOUTS =
|
||||
Arrays.asList("center", "center-left", "center-right", "top", "top-left", "top-right");
|
||||
private static final String LEFT = "left";
|
||||
private static final String RIGHT = "right";
|
||||
private static final String TOP = "top";
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
@(gid: String, deps: com.gitpitch.policies.Dependencies)
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<title>GitPitch - Get the word out about your GitHub projects.</title>
|
||||
<script src="@deps.jquery(false)/jquery.min.js"></script>
|
||||
<script src="@deps.gitpitchjs(false)/gist-embed-2.5.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<code data-gist-id="@gid" data-gist-hide-footer="true"></code>
|
||||
</body>
|
||||
</html>
|
|
@ -1,48 +0,0 @@
|
|||
@(rndr: com.gitpitch.utils.GitRepoRenderer, deps: com.gitpitch.policies.Dependencies, offline: Boolean)
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]>
|
||||
<html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
||||
<!--[if IE 7]>
|
||||
<html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
||||
<!--[if IE 8]>
|
||||
<html class="no-js lt-ie9"> <![endif]-->
|
||||
<!--[if gt IE 8]><!-->
|
||||
<html class="no-js"> <!--<![endif]-->
|
||||
<body>
|
||||
<div class="pitch-menu">
|
||||
<div class="pitch-menu-logo"></div>
|
||||
<br><br>
|
||||
<div class="git-box">
|
||||
<div style="padding-top: 25px; padding-bottom: 10px;">
|
||||
<span class="git-octicon">
|
||||
<span class="octicon octicon-git-branch">
|
||||
<span style="padding-left: 5px;">
|
||||
Choose Git Service
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<hr class="fade-away">
|
||||
<br>
|
||||
<ul class="slide-menu-items slide-menu-boxed">
|
||||
@for(grs <- rndr.listGRS()) {
|
||||
@if(grs.getType() == rndr.params().grs) {
|
||||
<li class="home-git slide-menu-item selected">
|
||||
<a class="active" href='@rndr.pageLink(false, grs.getType())'>@grs.getName()</a>
|
||||
</li>
|
||||
} else {
|
||||
<li class="home-git slide-menu-item">
|
||||
<a href='@rndr.pageLink(false, grs.getType())'>@grs.getName()</a>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
<br>
|
||||
</div>
|
||||
<br><br>
|
||||
<p>Just add <a href="https://github.com/gitpitch/gitpitch/wiki"
|
||||
style="text-decoration: none">PITCHME.md</a>.</p>
|
||||
<p>Then Git-Commit.</p>
|
||||
<br>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,114 +0,0 @@
|
|||
@import com.gitpitch.views.html.frags._
|
||||
|
||||
@(rndr: com.gitpitch.utils.GitRepoRenderer,
|
||||
deps: com.gitpitch.policies.Dependencies,
|
||||
offline: Boolean,
|
||||
userAgentIsChrome: Boolean)
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]>
|
||||
<html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
||||
<!--[if IE 7]>
|
||||
<html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
||||
<!--[if IE 8]>
|
||||
<html class="no-js lt-ie9"> <![endif]-->
|
||||
<!--[if gt IE 8]><!-->
|
||||
<html class="no-js"> <!--<![endif]-->
|
||||
<body>
|
||||
<div class="pitch-menu">
|
||||
<div class="pitch-menu-logo"></div>
|
||||
<br><br>
|
||||
<div class="git-box">
|
||||
<div style="padding-top: 25px; padding-bottom: 10px;">
|
||||
<span class="git-octicon">
|
||||
@Html(rndr.getGRSIcon(rndr.params()))
|
||||
<span style="padding-left: 5px;">
|
||||
@rndr.getGRS(rndr.params()) Slideshow
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<hr class="fade-away">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="git-label">User:</td>
|
||||
<td><a href="@rndr.orgHub()" target="_blank">
|
||||
<div class="short-link">@rndr.user()</div>
|
||||
</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="git-label">Repo:</td>
|
||||
<td><a href="@rndr.repoHub()" target="_blank">
|
||||
<div class="short-link">@rndr.repo()</div>
|
||||
</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="git-label">Branch:</td>
|
||||
<td><a href="@rndr.branchHub(rndr.params())" target="_blank">
|
||||
<div class="short-link">@rndr.branch()</div>
|
||||
</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="git-label">Slides:</td>
|
||||
<td><a href="@rndr.pitchHub(rndr.params())" target="_blank">
|
||||
<div class="short-link">@rndr.pitchme()</div>
|
||||
</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr class="fade-away">
|
||||
<table style="margin: 0 auto">
|
||||
<tr>
|
||||
<td class="git-octicon">
|
||||
<span class="octicon octicon-star">
|
||||
<span class="star-fork">
|
||||
@rndr.stargazers()
|
||||
</span>
|
||||
</td>
|
||||
<td class="git-octicon">
|
||||
<span class="octicon octicon-repo-forked">
|
||||
<span class="star-fork">
|
||||
@rndr.forks()
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr class="fade-away">
|
||||
@if(!offline) {
|
||||
<ul>
|
||||
<li class="slideshow"
|
||||
title="Download GitPitch presentation for offline use.">
|
||||
<a href="@rndr.offlineLink()" target="_blank">
|
||||
<i class="fa fa-download" aria-hidden="true">
|
||||
</i> Offline Version (.zip)</a>
|
||||
</li>
|
||||
<li class="slideshow"
|
||||
title="Convert GitPitch presentation to PDF doc for printing.">
|
||||
<a href="@rndr.printLink()" target="_blank">
|
||||
<i class="fa fa-external-link" aria-hidden="true">
|
||||
</i> Print Version (.pdf)</a>
|
||||
</li>
|
||||
<li class="slideshow">
|
||||
<a href="@rndr.twitterLink()" target="_blank"
|
||||
title="Share link to GitPitch presentation on Twitter."
|
||||
style="padding-left: 0px; padding-right:10px">
|
||||
<i class="fa fa-twitter" aria-hidden="true">
|
||||
</i> Twitter</a>
|
||||
<a href="@rndr.linkedInLink()" target="_blank"
|
||||
title="Share link to GitPitch presentation on LinkedIn.">
|
||||
<i class="fa fa-linkedin-square" aria-hidden="true">
|
||||
</i> LinkedIn</a>
|
||||
</li>
|
||||
<li class="slideshow"
|
||||
title="Open the GitPitch Wiki for detailed How-To help.">
|
||||
<a href="https://github.com/gitpitch/gitpitch/wiki" target="_blank">
|
||||
<i class="fa fa-question-circle" aria-hidden="true">
|
||||
</i> Help</a>
|
||||
</li>
|
||||
</ul>
|
||||
}
|
||||
<br>
|
||||
</div>
|
||||
<br><br>
|
||||
<p>Promote, Pitch, Or Present</p><p>Absolutely Anything.</p>
|
||||
<br>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,46 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
height: 100vh;
|
||||
min-height: 100vh;
|
||||
background-image: url(https://gitpitch.com/gp-splash.svg);
|
||||
background-position: center;
|
||||
background-size: 60%;
|
||||
background-color: black;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
div.not-found {
|
||||
color: white;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
font-size: 1.2em;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
div.top {
|
||||
top: 40px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
div.bottom {
|
||||
bottom: 40px;
|
||||
}
|
||||
div.byline {
|
||||
padding-top: 8px;
|
||||
}
|
||||
div.gray {
|
||||
color: #b3b3be;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="not-found top">Presentation Not Found
|
||||
<div class="byline gray">Invalid URL</div>
|
||||
</div>
|
||||
<div class="not-found bottom gray">Valid Presentation URL Format
|
||||
<div class="byline gray">https://gitpitch.com/$user/$repo/$branch</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,17 +0,0 @@
|
|||
@(pembed: com.gitpitch.oembed.PitchEmbed)
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<oembed>
|
||||
<version>1.0</version>
|
||||
<type>rich</type>
|
||||
<title>@pembed.title</title>
|
||||
<author-name>@pembed.author_name</author-name>
|
||||
<author-url>@pembed.author_url</author-url>
|
||||
<provider-name>@pembed.provider_name</provider-name>
|
||||
<provider-url>@pembed.provider_url</provider-url>
|
||||
<html>@pembed.html</html>
|
||||
<width type="integer">@pembed.width</width>
|
||||
<height type="integer">@pembed.height</height>
|
||||
<thumbnail_url>@pembed.thumbnail_url</thumbnail_url>
|
||||
<thumbnail_width>@pembed.thumbnail_width</thumbnail_width>
|
||||
<thumbnail_height>@pembed.thumbnail_height</thumbnail_height>
|
||||
</oembed>
|
|
@ -1,61 +0,0 @@
|
|||
@import com.gitpitch.views.html.frags._
|
||||
|
||||
@(ssm: com.gitpitch.models.SlideshowModel,
|
||||
rndr: com.gitpitch.utils.GitRepoRenderer,
|
||||
deps: com.gitpitch.policies.Dependencies,
|
||||
gpToken: String,
|
||||
offline: Boolean,
|
||||
serverPrinting: Boolean,
|
||||
webPrinting: Boolean)
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<title>@ssm.params().asTitle()</title>
|
||||
<meta content="Markdown Presentation powered by GitPitch." name="description">
|
||||
<meta content="GitHub, GitLab, Bitbucket, Markdown, Slideshow, Presentation, Developers, PITCHME" name="keywords">
|
||||
@SlideshowOEmbedDiscovery(rndr)
|
||||
@SlideshowStyleDependencies(ssm, deps, offline, webPrinting)
|
||||
@SlideshowRevealCoreOverrides(ssm)
|
||||
@SlideshowMenuStyle(offline)
|
||||
@SlideshowNotificationBarStyle(ssm)
|
||||
@SlideshowCodeFragHighlightStyle()
|
||||
@SlideshowThemeOverride(ssm)
|
||||
@SlideshowGoogleAnalytics(ssm, offline, serverPrinting, gpToken)
|
||||
</head>
|
||||
<body>
|
||||
@SlideshowLogo(ssm, offline)
|
||||
<div class="reveal">
|
||||
<div class="slides">
|
||||
@if(offline) {
|
||||
<section data-markdown="./assets/md/PITCHME.md"
|
||||
data-separator="@ssm.fetchHorzDelim()"
|
||||
data-separator-vertical="@ssm.fetchVertDelim()"
|
||||
data-separator-notes="^Note:"
|
||||
data-charset="utf-8">
|
||||
</section>
|
||||
} else {
|
||||
<section data-markdown="@ssm.fetchMarkdown()"
|
||||
data-separator="@ssm.fetchHorzDelim()"
|
||||
data-separator-vertical="@ssm.fetchVertDelim()"
|
||||
data-separator-notes="^Note:"
|
||||
data-charset="utf-8">
|
||||
</section>
|
||||
}
|
||||
</div>
|
||||
@SlideshowPresentingFooter(ssm, serverPrinting, webPrinting)
|
||||
</div>
|
||||
<div class="gp-menu"></div>
|
||||
@SlideshowPrintFooter(ssm, serverPrinting, webPrinting)
|
||||
|
||||
<script src="@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/js/reveal.js"></script>
|
||||
<script src="@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/lib/js/head.min.js"></script>
|
||||
<script src="@deps.jquery(offline)/jquery.min.js"></script>
|
||||
|
||||
@SlideshowReveal(ssm, deps, offline, serverPrinting, webPrinting)
|
||||
@SlideshowNotifications(ssm, serverPrinting, webPrinting)
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,70 +0,0 @@
|
|||
@(rndr: com.gitpitch.utils.GitRepoRenderer,
|
||||
deps: com.gitpitch.policies.Dependencies,
|
||||
fixedTheme: String,
|
||||
offline: Boolean)
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]>
|
||||
<html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
||||
<!--[if IE 7]>
|
||||
<html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
||||
<!--[if IE 8]>
|
||||
<html class="no-js lt-ie9"> <![endif]-->
|
||||
<!--[if gt IE 8]><!-->
|
||||
<html class="no-js"> <!--<![endif]-->
|
||||
<body>
|
||||
<div class="pitch-menu">
|
||||
<div class="pitch-menu-logo"></div>
|
||||
<br><br>
|
||||
<div class="git-box">
|
||||
<div style="padding-top: 25px; padding-bottom: 10px;">
|
||||
<span class="git-octicon">
|
||||
<span class="octicon octicon-file-media">
|
||||
<span style="padding-left: 5px;">
|
||||
Choose Theme
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<hr class="fade-away">
|
||||
<br>
|
||||
<ul class="slide-menu-items slide-menu-boxed">
|
||||
@for(theme <- rndr.listThemes()) {
|
||||
@if(theme == fixedTheme || (fixedTheme == null && theme == rndr.theme())) {
|
||||
@if(theme == fixedTheme) {
|
||||
<li class="home-themes slide-menu-item selected fixed-theme">
|
||||
<a class="active" href='@rndr.pageLinkWithTheme(theme)'>@theme</a>
|
||||
</li>
|
||||
} else {
|
||||
<li class="home-themes slide-menu-item selected">
|
||||
<a class="active" href='@rndr.pageLinkWithTheme(theme)'>@theme</a>
|
||||
</li>
|
||||
}
|
||||
} else {
|
||||
@if(fixedTheme != null) {
|
||||
<li class="home-themes slide-menu-item disabled-theme">
|
||||
<a href='@rndr.pageLinkWithTheme(theme)'>@theme</a>
|
||||
</li>
|
||||
} else {
|
||||
<li class="home-themes slide-menu-item">
|
||||
<a href='@rndr.pageLinkWithTheme(theme)'>@theme</a>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
<br>
|
||||
</div>
|
||||
<br><br>
|
||||
@if(fixedTheme != null) {
|
||||
<p><a href="https://github.com/gitpitch/gitpitch/wiki/Slideshow-Settings"
|
||||
style="text-decoration: none">PITCHME.yaml</a></p>
|
||||
<p>Fixed theme in use.</p>
|
||||
</p>
|
||||
} else {
|
||||
<p>Use <a href="https://github.com/gitpitch/gitpitch/wiki"
|
||||
style="text-decoration: none">PITCHME.yaml</a> To</p>
|
||||
<p>Customize Everything.</p>
|
||||
}
|
||||
<br>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,16 +0,0 @@
|
|||
@(gaToken: String, gpu: Boolean)
|
||||
@if(gaToken != null) {
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
@if(gpu) {
|
||||
ga('create', '@gaToken', 'auto', 'gpu');
|
||||
ga('gpu.send', 'pageview');
|
||||
} else {
|
||||
ga('create', '@gaToken', 'auto');
|
||||
ga('send', 'pageview');
|
||||
}
|
||||
</script>
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
@(rndr: com.gitpitch.utils.GitRepoRenderer, offline: Boolean)
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-fixed-bottom">
|
||||
<div class="container-fluid">
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
|
||||
@if(offline) {
|
||||
<p class="navbar-text pull-left"><span style="color: white; font-weight:bold; font-size: 1.3em"> @rndr.getGRS(rndr.params())</span>
|
||||
</p>
|
||||
} else {
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" style="font-size:1.3em; font-weight:bold" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">@rndr.getGRS(rndr.params()) <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="dropdown-header">GitPitch Git Services</li>
|
||||
<li role="separator" class="divider"></li>
|
||||
@for(grs <- rndr.listGRS()) {
|
||||
<li><a href='@rndr.pageLink(false, grs.getType())'>@grs.getName()</a></li>
|
||||
}
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#popupTheme" role="button" data-toggle="modal-popover" data-placement="top"><i
|
||||
class="fa fa-paint-brush" aria-hidden="true"> <span style="font-family: Helvetica Neue"
|
||||
,Helvetica,Arial,sans-serif;">Theme</span>
|
||||
</i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#popupBadge" role="button" data-toggle="modal-popover" data-placement="top"><i
|
||||
class="fa fa-shield" aria-hidden="true"> <span style="font-family: Helvetica Neue"
|
||||
,Helvetica,Arial,sans-serif;">Badge</span>
|
||||
</i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#popupEmbed" role="button" data-toggle="modal-popover" data-placement="top"><i
|
||||
class="fa fa-link" aria-hidden="true"> <span style="font-family: Helvetica Neue"
|
||||
,Helvetica,Arial,sans-serif;">Embed</span>
|
||||
</i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#popupShare" role="button" data-toggle="modal-popover" data-placement="top"><i
|
||||
class="fa fa-share" aria-hidden="true"> <span style="font-family: Helvetica Neue"
|
||||
,Helvetica,Arial,sans-serif;">Share</span>
|
||||
</i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#popupPrint" role="button" data-toggle="modal-popover" data-placement="top"><i
|
||||
class="fa fa-print" aria-hidden="true"> <span style="font-family: Helvetica Neue",Helvetica,Arial,sans-serif;">Print</span>
|
||||
</i></a>
|
||||
</li>
|
||||
<li>
|
||||
@if(rndr.isValid()) {
|
||||
<a href="@rndr.offlineLink()" target="_blank"><i class="fa fa-plug" aria-hidden="true"> <span
|
||||
style="font-family: Helvetica Neue" ,Helvetica,Arial,sans-serif;">Offline</span></i></a>
|
||||
} else {
|
||||
<a title="Repo not found, print disabled."><i class="fa fa-plug" aria-hidden="true"> <span
|
||||
style="font-family: Helvetica Neue" ,Helvetica,Arial,sans-serif;">Offline</span></i></a>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li>
|
||||
@if(offline) {
|
||||
<a>[ Offline ]</a>
|
||||
} else {
|
||||
<a><span style="color:gray">[ Fullscreen: Press F ]</span></a>
|
||||
}
|
||||
</li>
|
||||
</ul>
|
||||
</div> <!-- navbar -->
|
||||
</div> <!-- container-fluid -->
|
||||
</nav>
|
|
@ -1,78 +0,0 @@
|
|||
@(rndr: com.gitpitch.utils.GitRepoRenderer, offline: Boolean)
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed"
|
||||
data-toggle="collapse" data-target="#navbar"
|
||||
aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
@if(offline) {
|
||||
<a class="navbar-brand" href="#">
|
||||
} else {
|
||||
<a class="navbar-brand" href="https://gitpitch.com">
|
||||
}
|
||||
<span style="letter-spacing: 0.1em;
|
||||
color:#e49436;
|
||||
font-size: 1.4em;
|
||||
font-weight: bold;
|
||||
text-transform:none">Git<span style="color:white">Pitch</span></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navbar" class="navbar-collapse collapse" style="margin-top: 3px">
|
||||
<ul class="nav navbar-nav">
|
||||
@if(offline) {
|
||||
<li style="font-size:1.2em; color:white"><a href="#">@rndr.user()</a></li>
|
||||
<li style="font-size:1.2em; color:white" class="hidden-sd hidden-xs"><p class="navbar-text" style="color:white">/</p></li>
|
||||
<li style="font-size:1.2em; color:white"><a href="#">@rndr.repo()</a></li>
|
||||
<li><a href="#" style="font-size:1.2em;color:gray" class="hidden-sd hidden-xs">{
|
||||
@rndr.displayLangOrBranch() }</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="visible-lg visible-md" style="font-size:1.1em; color:white"><a href="#"><span
|
||||
class="octicon octicon-star"></span> Star @rndr.stargazers()</a></li>
|
||||
<li class="visible-lg visible-md" style="font-size:1.1em; color:white"><a href="#"><span
|
||||
class="octicon octicon-repo-forked"></span> Fork @rndr.forks()</a></li>
|
||||
|
||||
@if(rndr.params().grs.equals("github")) {
|
||||
<li style="font-size:1.2em; color:white"><a href="#"><span class="mega-octicon octicon-mark-github" style="font-size:1.3em"></span></a></li>
|
||||
} else {
|
||||
<li style="font-size:1.2em; color:white"><a href="#"><span class="fa fa-@rndr.params().grs" aria-hidden="true" style="font-size:1.4em"></span></a></li>
|
||||
}
|
||||
|
||||
} else {
|
||||
<li style="font-size:1.2em; color:white"><a href="@rndr.orgHub()">@rndr.user()</a></li>
|
||||
<li style="font-size:1.2em; color:white" class="hidden-sd hidden-xs"><p class="navbar-text" style="color:white">/</p></li>
|
||||
<li style="font-size:1.2em; color:white"><a href="@rndr.repoHub()">@rndr.repo()</a></li>
|
||||
<li><a href="#" style="font-size:1.2em;color:gray" class="hidden-sd hidden-xs">{ @rndr.displayLangOrBranch() }</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="visible-lg visible-md" style="font-size:1.1em; color:white"><a href="@rndr.starHub()"><span
|
||||
class="octicon octicon-star"></span> Star @rndr.stargazers()</a></li>
|
||||
<li class="visible-lg visible-md" style="font-size:1.1em; color:white"><a href="@rndr.forkHub()"><span
|
||||
class="octicon octicon-repo-forked"></span> Fork @rndr.forks()</a></li>
|
||||
<li style="font-size:1.2em; color:white"><a href="@rndr.repoHub()">
|
||||
@if(rndr.params().grs.equals("github")) {
|
||||
<span class="mega-octicon octicon-mark-github" style="font-size:1.3em"></span>
|
||||
}
|
||||
@if(rndr.params().grs.equals("gitlab")) {
|
||||
<span class="fa fa-gitlab" aria-hidden="true" style="font-size:1.4em"></span>
|
||||
}
|
||||
@if(rndr.params().grs.equals("bitbucket")) {
|
||||
<span class="fa fa-bitbucket" aria-hidden="true" style="font-size:1.4em"></span>
|
||||
}
|
||||
@if(rndr.params().grs.equals("gitea") || rndr.params().grs.equals("gogs") ||
|
||||
rndr.params.grs.equals("gitbucket")) {
|
||||
<span class="fa fa-git-square" aria-hidden="true" style="font-size:1.4em"></span>
|
||||
}
|
||||
</a></li>
|
||||
}
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
|
@ -1,30 +0,0 @@
|
|||
@(deps: com.gitpitch.policies.Dependencies, offline: Boolean)
|
||||
|
||||
<script src="@deps.gitpitchjs(offline)/bootstrap-modal-popover-2.0.1.js"></script>
|
||||
<script src="@deps.gitpitchjs(offline)/clipboard-1.5.12.js"></script>
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('message',function(e) {
|
||||
var key = e.message ? 'message' : 'data';
|
||||
var data = e[key];
|
||||
if(data == 'FIXEDTHEME') {
|
||||
$( "#themes-popup-content" ).empty()
|
||||
.append("<span style='padding: 10px 10px'><a target='_blank' href='https://github.com/gitpitch/gitpitch/wiki/Theme-Setting'>PITCHME.yaml</a> fixed theme in use.</span>");
|
||||
}
|
||||
},false);
|
||||
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
new Clipboard('.btn');
|
||||
|
||||
</script>
|
||||
<script>
|
||||
var a2a_config = a2a_config || {};
|
||||
a2a_config.num_services = 5;
|
||||
a2a_config.color_main = "D7E5ED";
|
||||
a2a_config.color_border = "AECADB";
|
||||
a2a_config.color_link_text = "333333";
|
||||
a2a_config.color_link_text_hover = "333333";
|
||||
a2a_config.prioritize = ["twitter", "linkedin", "facebook", "google_plus", "slashdot"];
|
||||
|
||||
</script>
|
||||
<script async src="https://static.addtoany.com/menu/page.js"></script>
|
|
@ -1,99 +0,0 @@
|
|||
@(rndr: com.gitpitch.utils.GitRepoRenderer)
|
||||
|
||||
<div id="popupTheme" class="popover" style="text-align: center; font-size:1em">
|
||||
<div class="arrow"></div>
|
||||
<h5 class="popover-title">GitPitch Themes</h5>
|
||||
<div id="themes-popup-content" class="popover-content themes">
|
||||
@if(rndr.isValid()) {
|
||||
<p style="width:215px; font-size:0.9em">Theme Switcher</p>
|
||||
<hr style="margin-bottom: 10px; margin-top: 10px">
|
||||
<a href='@rndr.pageLinkWithTheme("black")''>Black</a> -
|
||||
<a href='@rndr.pageLinkWithTheme("moon")''>Moon</a> -
|
||||
<a href='@rndr.pageLinkWithTheme("night")''>Night</a>
|
||||
<hr style="margin-bottom: 10px; margin-top: 10px">
|
||||
<a href='@rndr.pageLinkWithTheme("beige")''>Beige</a> -
|
||||
<a href='@rndr.pageLinkWithTheme("sky")''>Sky</a> -
|
||||
<a href='@rndr.pageLinkWithTheme("white")''>White</a>
|
||||
<hr style="margin-bottom: 10px; margin-top: 10px">
|
||||
<p style="width:215px; font-size:0.8em; color: gray">Tip: Use <b>PITCHME.yaml</b> to set a fixed theme for
|
||||
your slideshow.</p>
|
||||
} else {
|
||||
Repo not found, themes disabled.
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div id="popupBadge" class="popover" style="text-align: center; font-size:1em">
|
||||
<div class="arrow"></div>
|
||||
<h5 class="popover-title">GitPitch Badge</h5>
|
||||
<div class="popover-content">
|
||||
@if(rndr.isValid()) {
|
||||
<p style="width:215px; font-size:0.9em">Use the following markdown snippet to add a badge for this slideshow
|
||||
to the README.md for your repo.</p>
|
||||
<img src='@routes.Assets.versioned("badge.svg")'/>
|
||||
<hr style="margin-bottom: 10px; margin-top: 10px">
|
||||
<input id="badgeSnippet" value="@Html(rndr.pageBadge())"></input>
|
||||
<button class="btn" data-clipboard-target="#badgeSnippet">
|
||||
<i class="fa fa-clipboard" aria-hidden="true"></i>
|
||||
</button>
|
||||
} else {
|
||||
Repo not found, badge disabled.
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div id="popupEmbed" class="popover" style="text-align: center; font-size:1em">
|
||||
<div class="arrow"></div>
|
||||
<h5 class="popover-title">GitPitch Embed</h5>
|
||||
<div class="popover-content">
|
||||
@if(rndr.isValid()) {
|
||||
<p style="width:215px; font-size:0.9em">Use the following snippet to embed this GitPitch in your website or
|
||||
blog.</p>
|
||||
<hr style="margin-bottom: 10px; margin-top: 10px">
|
||||
<input id="embedSnippet" value="@Html(rndr.pageEmbed())"></input>
|
||||
<button class="btn" data-clipboard-target="#embedSnippet">
|
||||
<i class="fa fa-clipboard" aria-hidden="true"></i>
|
||||
</button>
|
||||
} else {
|
||||
Repo not found, embed disabled.
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div id="popupShare" class="popover" style="text-align: center; font-size:1em">
|
||||
<div class="arrow"></div>
|
||||
<h5 class="popover-title">GitPitch Share</h5>
|
||||
<div class="popover-content">
|
||||
@if(rndr.isValid()) {
|
||||
<p style="width:215px">Help get the word out about this GitPitch by e-mail or social media.</p>
|
||||
<hr style="margin-bottom: 10px; margin-top: 10px">
|
||||
<input id="shareSnippet" value="@rndr.pageLink(true)"></input>
|
||||
<button class="btn" data-clipboard-target="#shareSnippet">
|
||||
<i class="fa fa-clipboard" aria-hidden="true"></i>
|
||||
</button>
|
||||
<hr style="margin-bottom: 10px; margin-top: 10px">
|
||||
<div class="a2a_kit a2a_kit_size_32 a2a_default_style">
|
||||
<a class="a2a_dd" href="https://www.addtoany.com/share"></a>
|
||||
<a class="a2a_button_email"></a>
|
||||
<a class="a2a_button_twitter"></a>
|
||||
<a class="a2a_button_linkedin"></a>
|
||||
<a class="a2a_button_facebook"></a>
|
||||
<a class="a2a_button_google_plus"></a>
|
||||
</div>
|
||||
} else {
|
||||
Repo not found, share disabled.
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div id="popupPrint" class="popover" style="text-align: center; font-size:1em">
|
||||
<div class="arrow"></div>
|
||||
<h5 class="popover-title">GitPitch Printing</h5>
|
||||
<div class="popover-content">
|
||||
@if(rndr.isValid()) {
|
||||
<a href="@rndr.printLink()" target="_blank">Generate PDF on Server</a>
|
||||
<hr style="margin-bottom: 10px; margin-top: 10px">
|
||||
<a href="@rndr.printBrowserLink()" target="_blank">Generate PDF in Browser</a>
|
||||
<hr style="margin-bottom: 10px; margin-top: 10px">
|
||||
<p style="width:215px; font-size:0.8em; color: gray">Note: Browser support in <b>Chrome</b> only.
|
||||
} else {
|
||||
Repo not found, printing disabled.
|
||||
}
|
||||
</div>
|
||||
</div>
|
|
@ -1,36 +0,0 @@
|
|||
@(deps: com.gitpitch.policies.Dependencies, offline: Boolean)
|
||||
|
||||
<style>
|
||||
.navbar-brand {
|
||||
padding: 17px;
|
||||
}
|
||||
.navbar-inverse .navbar-nav > li > a {
|
||||
color: white;
|
||||
}
|
||||
.navbar-inverse .navbar-nav > li > a:hover {
|
||||
color: #e49436;
|
||||
}
|
||||
.navbar-inverse .navbar-nav > li > a:visited {
|
||||
color: white;
|
||||
}
|
||||
.themes > a {
|
||||
color: #e49436;
|
||||
}
|
||||
.shortcut > a{
|
||||
color: #e49436;
|
||||
font-weight: bold;
|
||||
}
|
||||
#slideshow {
|
||||
background-image: url('@deps.gitpitchimg(offline)/preloader-75.gif');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
.centered {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size:1.3em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -1,18 +0,0 @@
|
|||
<style>
|
||||
.reveal .slides section .code-presenting-annotation {
|
||||
font-size: 70%;
|
||||
}
|
||||
.reveal .slides section .fragment.current-only {
|
||||
visibility: visible;
|
||||
display: none;
|
||||
}
|
||||
.reveal .slides section .fragment.current-only.current-fragment {
|
||||
display: block;
|
||||
}
|
||||
.line {
|
||||
display: block;
|
||||
}
|
||||
.line.focus {
|
||||
/* opacity: 1.0; */
|
||||
}
|
||||
</style>
|
|
@ -1,11 +0,0 @@
|
|||
@(ssm: com.gitpitch.models.SlideshowModel, offline: Boolean, serverPrinting: Boolean, gpToken: String)
|
||||
@if(!offline) {
|
||||
@if(!serverPrinting) {
|
||||
@if(gpToken) {
|
||||
@GoogleAnalytics(gpToken, false)
|
||||
}
|
||||
@if(ssm.hasGAToken()) {
|
||||
@GoogleAnalytics(ssm.fetchGAToken(), true)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
@(ssm: com.gitpitch.models.SlideshowModel, offline: Boolean)
|
||||
@if(ssm.hasLogo()) {
|
||||
<div id="gp-logo" style="@ssm.fetchLogoPosition()">
|
||||
@if(offline) {
|
||||
<img src="./assets/@ssm.fetchLogoName()"/>
|
||||
} else {
|
||||
<img src="@ssm.fetchLogo()"/>
|
||||
}
|
||||
</div>
|
||||
}
|
|
@ -1,142 +0,0 @@
|
|||
@(offline: Boolean)
|
||||
<style>
|
||||
/* GitPitch Styling */
|
||||
.centered {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size:1.3em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.reveal .controls {
|
||||
bottom: 20px;
|
||||
}
|
||||
/* GitPitch Menu Styling */
|
||||
.gp-menu-bars {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
div.pitch-menu {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
div.pitch-menu-logo {
|
||||
height: 90px;
|
||||
margin: 0 auto;
|
||||
background-size: 280px 90px;
|
||||
background-repeat: no-repeat;
|
||||
@if(offline) {
|
||||
background-image: url(assets/img/gp-logo-tagline.svg);
|
||||
} else {
|
||||
background-image: url(https://gitpitch.com/gp-logo-tagline.svg);
|
||||
}
|
||||
}
|
||||
div.pitch-menu div.section-heading {
|
||||
display: none;
|
||||
color: white;
|
||||
font-size: 1.1em;
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
}
|
||||
div.pitch-menu .git-box {
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
border: 1px solid gray;
|
||||
border-radius: 5px;
|
||||
}
|
||||
div.git-box > table:first-of-type {
|
||||
margin-left: 8%;
|
||||
}
|
||||
div.git-box, div.git-octicon, .git-octicon span {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
div.pitch-menu .git-box .short-link {
|
||||
width: 8em;
|
||||
font-size: 1em;
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
div.pitch-menu .git-box a {
|
||||
font-size: 1em;
|
||||
text-decoration:none;
|
||||
}
|
||||
div.pitch-menu .git-box a a:hover {
|
||||
color: #e48436;
|
||||
}
|
||||
div.pitch-menu .git-box table th, div.pitch-menu table td {
|
||||
text-align: left;
|
||||
padding: 0.6em 0.3em 0.6em 0.3em;
|
||||
border: 0;
|
||||
}
|
||||
div.pitch-menu .git-label {
|
||||
color: #b3b3b3;
|
||||
font-size: 1em;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
div.pitch-menu .git-octicon {
|
||||
font: normal normal normal 16px/1 octicons;
|
||||
font-size:1.1em;
|
||||
color: white;
|
||||
}
|
||||
div.pitch-menu .git-octicon .star-fork {
|
||||
padding-left: 4px;
|
||||
color: white;
|
||||
}
|
||||
span.octicon.octicon-star, span.octicon.octicon-repo-forked {
|
||||
color: #fff;
|
||||
}
|
||||
span.octicon span.star-fork {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
font-size: 90%;
|
||||
}
|
||||
.git-octicon span.octicon {
|
||||
font-family: octicons;
|
||||
/* font-weight: bold !important; */
|
||||
}
|
||||
div.pitch-menu ul {
|
||||
list-style-type: none;
|
||||
margin: 14px 0 0px 0;
|
||||
}
|
||||
div.pitch-menu ul li.slideshow {
|
||||
font-size: 0.95em;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
padding: 10px 0;
|
||||
}
|
||||
div.pitch-menu ul li.home-git {
|
||||
padding: 14px 0 14px 0;
|
||||
font-size: 1.0em;
|
||||
letter-spacing: 1.5px;
|
||||
text-align: center;
|
||||
}
|
||||
div.pitch-menu ul li.home-git a {
|
||||
font-family: 'Roboto', sans-serif !important;
|
||||
}
|
||||
div.pitch-menu ul li.home-themes {
|
||||
padding: 14px 0 14px 0;
|
||||
font-size: 1.0em;
|
||||
text-transform: capitalize;
|
||||
letter-spacing: 1.5px;
|
||||
text-align: center;
|
||||
border-top: solid 1px #222;
|
||||
}
|
||||
div.pitch-menu ul li.home-themes a {
|
||||
font-family: 'Roboto', sans-serif !important;
|
||||
}
|
||||
hr.fade-away {
|
||||
border: 0;
|
||||
height: 1px;
|
||||
background: #999;
|
||||
background-image: linear-gradient(to right, #666, #999, #666);
|
||||
width: 80%;
|
||||
}
|
||||
div.pitch-menu ul i.fa.fa-download, div.pitch-menu ul i.fa.fa-print, div.pitch-menu ul i.fa.fa-external-link {
|
||||
padding-right: 5px;
|
||||
}
|
||||
</style>
|
|
@ -1,40 +0,0 @@
|
|||
@(ssm: com.gitpitch.models.SlideshowModel)
|
||||
<style>
|
||||
#title-footer.footer-visible {
|
||||
display: inline;
|
||||
}
|
||||
#title-footer.footer-hidden {
|
||||
display: none;
|
||||
}
|
||||
#title-footer #notification {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
#title-footer p {
|
||||
text-align: center;
|
||||
font-size: 0.9em;
|
||||
line-height: 1;
|
||||
margin: 0;
|
||||
padding-top: 2px;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
#title-footer p.footer-hard {
|
||||
@if(ssm.isDarkTheme()) {
|
||||
color: #bbb;
|
||||
} else {
|
||||
color: #4d4d4d;
|
||||
}
|
||||
}
|
||||
#title-footer p.footer-fade {
|
||||
@if(ssm.isDarkTheme()) {
|
||||
color: #bbb;
|
||||
opacity: 0.9;
|
||||
} else {
|
||||
color: #4d4d4d;
|
||||
opacity: 0.9;
|
||||
}
|
||||
font-size: 1.5vh;
|
||||
letter-spacing: 0;
|
||||
padding-top: 3px;
|
||||
}
|
||||
</style>
|
|
@ -1,47 +0,0 @@
|
|||
@(ssm: com.gitpitch.models.SlideshowModel, serverPrinting: Boolean, webPrinting: Boolean)
|
||||
@if(!(serverPrinting || webPrinting)) {
|
||||
<script>
|
||||
function pushNotification(msg, fade) {
|
||||
var footer = document.getElementById('title-footer')
|
||||
var notification = document.getElementById('notification')
|
||||
if(window.innerWidth < 700) {
|
||||
footer.className = "footer-hidden";
|
||||
} else {
|
||||
footer.className = "footer-visible";
|
||||
if(fade) {
|
||||
notification.className = "footer-fade";
|
||||
notification.innerHTML = msg;
|
||||
} else {
|
||||
notification.className = "footer-hard";
|
||||
notification.innerHTML = msg;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function pushHelpNotification() {
|
||||
if(window.innerWidth < 700)
|
||||
pushNotification("@Html(ssm.fetchHelp(true))");
|
||||
else
|
||||
pushNotification("@Html(ssm.fetchHelp(false))");
|
||||
}
|
||||
|
||||
function pushFootnoteNotification() {
|
||||
@if(ssm.hasFootnote() && ssm.fetchFootnote().length() != 0) {
|
||||
pushNotification("@Html(ssm.fetchFootnote())", true);
|
||||
} else {
|
||||
pushNotification("[ GitPitch @Html(ssm.params().atPretty()) ]", true);
|
||||
}
|
||||
}
|
||||
|
||||
function pushCodePresentingStepNotification(step, frags) {
|
||||
pushNotification("Code Presenting - Step " + step + " / " + frags, true);
|
||||
}
|
||||
</script>
|
||||
} else {
|
||||
<script>
|
||||
function pushNotification(msg, fade) {};
|
||||
function pushHelpNotification() {}
|
||||
function pushFootnoteNotification() {}
|
||||
function pushCodePresentingStepNotification(step, frags) {}
|
||||
</script>
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
@(rndr: com.gitpitch.utils.GitRepoRenderer)
|
||||
<link rel="alternate" type="application/json+oembed" href='@rndr.oembed(rndr.slideshowAbs(), "json")' title="GitPitch - Markdown Presentations for Everyone on Git" />
|
||||
<link rel="alternate" type="text/xml+oembed" href='@rndr.oembed(rndr.slideshowAbs(), "xml")' title="GitPitch - Markdown Presentations for Everyone on Git" />
|
|
@ -1,4 +0,0 @@
|
|||
@(ssm: com.gitpitch.models.SlideshowModel, serverPrinting: Boolean, webPrinting: Boolean)
|
||||
@if(!(serverPrinting || webPrinting)) {
|
||||
<footer id="title-footer"><p id="notification"></p></footer>
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
@(ssm: com.gitpitch.models.SlideshowModel, serverPrinting: Boolean, webPrinting: Boolean)
|
||||
@if(serverPrinting || webPrinting) {
|
||||
<div style="position: fixed; bottom: 10px; left: 20px; z-index: 999">
|
||||
@if(ssm.hasFootnote()) {
|
||||
<span style="color:@ssm.fetchThemeFontColorInverse(); font-size:0.8em; font-family: @ssm.fetchThemeFont();">@Html(ssm.fetchFootnote())</span>
|
||||
} else {
|
||||
@if(ssm.params().grs.equals("github")) {
|
||||
<span class="octicon octicon-mark-github"
|
||||
style="font-size:0.9em; color: @ssm.fetchThemeFontColorInverse()"></span>
|
||||
}
|
||||
@if(ssm.params().grs.equals("gitlab")) {
|
||||
<i class="fa fa-gitlab" aria-hidden="true"
|
||||
style="font-size:0.9em; color: @ssm.fetchThemeFontColorInverse()"></i>
|
||||
}
|
||||
@if(ssm.params().grs.equals("bitbucket")) {
|
||||
<i class="fa fa-bitbucket" aria-hidden="true"
|
||||
style="font-size:0.9em; color: @ssm.fetchThemeFontColorInverse()"></i>
|
||||
}
|
||||
@if(ssm.params().grs.equals("gitea") || ssm.params().grs.equals("gogs") ||
|
||||
ssm.params().grs.equals("gitbucket")) {
|
||||
<i class="fa fa-git-square" aria-hidden="true"
|
||||
style="font-size:0.9em; color: @ssm.fetchThemeFontColorInverse()"></i>
|
||||
}
|
||||
<span style="color:@ssm.fetchThemeFontColorInverse(); font-size:0.8em; font-family: @ssm.fetchThemeFont();">@ssm.params().asLogo()</span>
|
||||
}
|
||||
</div>
|
||||
}
|
|
@ -1,205 +0,0 @@
|
|||
@(ssm: com.gitpitch.models.SlideshowModel, deps: com.gitpitch.policies.Dependencies, offline:Boolean, serverPrinting: Boolean, webPrinting: Boolean)
|
||||
|
||||
<script>
|
||||
Reveal.initialize({
|
||||
@if(!(serverPrinting || webPrinting)) {
|
||||
controls: true,
|
||||
} else {
|
||||
controls: false,
|
||||
}
|
||||
controlsLayout: '@ssm.fetchControlsLayout()',
|
||||
progress: true,
|
||||
embedded: true,
|
||||
margin: 0.0,
|
||||
showNotes: @ssm.showNotes(),
|
||||
transition: '@ssm.fetchTransition()',
|
||||
backgroundTransition: '@ssm.fetchTransition()',
|
||||
autoSlide: @ssm.fetchAutoSlide(false),
|
||||
loop: @ssm.fetchLoop(),
|
||||
center: @ssm.fetchVerticalCenter(),
|
||||
rtl: @ssm.fetchRTL(),
|
||||
shuffle: @ssm.fetchShuffle(),
|
||||
mouseWheel: @ssm.fetchMouseWheel(),
|
||||
@if(!(serverPrinting || webPrinting)) {
|
||||
slideNumber: 'c/t', // slideNumber: @ssm.fetchSlideNumber(),
|
||||
} else {
|
||||
slideNumber: false,
|
||||
}
|
||||
history: @ssm.fetchHistory(),
|
||||
@if(ssm.mathEnabled()) {
|
||||
math: {
|
||||
@if(offline) {
|
||||
mathjax: '@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/plugin/math/MathJax.js',
|
||||
} else {
|
||||
mathjax: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js',
|
||||
}
|
||||
config: '@ssm.fetchMathConfig()'
|
||||
},
|
||||
}
|
||||
@if(!(serverPrinting || webPrinting ||
|
||||
ssm.fetchAutoSlide(false) > 0)) {
|
||||
menu: {
|
||||
custom: [
|
||||
@if(offline) {
|
||||
{ title: 'Home', active: true,
|
||||
icon: '<i class="fa fa-bookmark">',
|
||||
src: 'menu.html' }
|
||||
} else {
|
||||
{ title: 'Home', active: true,
|
||||
icon: '<i class="fa fa-bookmark">',
|
||||
src: '@ssm.homePanel()' },
|
||||
@if(!ssm.published()) {
|
||||
{ title: 'Themes',
|
||||
icon: '<i class="fa fa-code-fork">',
|
||||
src: '@ssm.gitPanel()' },
|
||||
{ title: 'GRS',
|
||||
icon: '<i class="fa fa-image">',
|
||||
src: '@ssm.themesPanel()' }
|
||||
}
|
||||
}
|
||||
],
|
||||
path : "@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/plugin/menu",
|
||||
themes : false,
|
||||
transitions: false,
|
||||
markers: true,
|
||||
sticky: true,
|
||||
autoOpen: true
|
||||
},
|
||||
}
|
||||
dependencies: [
|
||||
{ src: "@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/plugin/markdown/marked.js",
|
||||
condition: function() {
|
||||
return !!document.querySelector( '[data-markdown]' );
|
||||
}},
|
||||
{ src: "@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/plugin/markdown/markdown.js",
|
||||
condition: function() {
|
||||
return !!document.querySelector( '[data-markdown]' );
|
||||
}},
|
||||
@if(!(serverPrinting || webPrinting)) {
|
||||
{ src:"@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/plugin/menu/menu-mod.js",
|
||||
async: true},
|
||||
}
|
||||
@if(ssm.chartsEnabled()) {
|
||||
{ src: "@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/plugin/chart/Chart.min.js"},
|
||||
{ src: "@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/plugin/chart/csv2chart.js"},
|
||||
}
|
||||
@if(deps.cdnDisabled() || offline) {
|
||||
{ src: "@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/plugin/notes/notes.js",
|
||||
async: true },
|
||||
}
|
||||
@if(deps.highlightPluginEnabled()) {
|
||||
{ src: "@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/plugin/highlight/highlight.js",
|
||||
async: true, callback: function() {
|
||||
hljs.initHighlightingOnLoad();
|
||||
} },
|
||||
} else {
|
||||
{ src: '@deps.highlightjs(offline)/highlight.js', async: true },
|
||||
{ src: '@deps.highlightjs(offline)/reveal-code-focus-1.0.0-mod.js',
|
||||
async: true,
|
||||
callback: function() {
|
||||
RevealCodeFocus();
|
||||
}
|
||||
},
|
||||
}
|
||||
@if(ssm.mathEnabled()) {
|
||||
{ src: "@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/plugin/math/math.js",
|
||||
async: true }
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
Reveal.addEventListener('ready', function(evt) {
|
||||
|
||||
upgradeAnchors();
|
||||
|
||||
if (evt.indexh === 0 && evt.indexv === 0) {
|
||||
pushHelpNotification();
|
||||
} else {
|
||||
pushFootnoteNotification();
|
||||
}
|
||||
});
|
||||
|
||||
Reveal.addEventListener('menu-ready', function(evt) {
|
||||
manageMenuPolicy();
|
||||
});
|
||||
|
||||
Reveal.addEventListener('slidechanged', function(evt) {
|
||||
if (evt.indexh === 0 && evt.indexv === 0) {
|
||||
pushHelpNotification();
|
||||
} else {
|
||||
pushFootnoteNotification();
|
||||
}
|
||||
});
|
||||
|
||||
Reveal.configure({
|
||||
keyboard: {
|
||||
88: function() { // bind "x" key to "select" code block content
|
||||
|
||||
var currentSlide = Reveal.getCurrentSlide();
|
||||
var preBlock = $(currentSlide).find("pre");
|
||||
|
||||
if(preBlock.length > 0) {
|
||||
|
||||
if (window.getSelection) {
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents(preBlock[0]);
|
||||
var selection = window.getSelection();
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function enterFullscreen() {
|
||||
Reveal.triggerKey(70);
|
||||
};
|
||||
|
||||
function enterOverview() {
|
||||
Reveal.toggleOverview();
|
||||
};
|
||||
|
||||
function enterBlackout() {
|
||||
Reveal.togglePause();
|
||||
};
|
||||
|
||||
function enterHelp() {
|
||||
Reveal.toggleHelp();
|
||||
}
|
||||
|
||||
function enableEvents() {
|
||||
Reveal.addEventListeners();
|
||||
};
|
||||
|
||||
function disableEvents() {
|
||||
Reveal.removeEventListeners();
|
||||
};
|
||||
|
||||
function manageMenuPolicy() {
|
||||
if(RevealMenu && RevealMenu.isOpen()) {
|
||||
RevealMenu.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
function upgradeAnchors() {
|
||||
Array.from(document.getElementsByTagName('a')).forEach($link => {
|
||||
if ($link.hostname !== window.location.hostname) {
|
||||
$link.setAttribute('rel', 'noopener noreferrer');
|
||||
$link.setAttribute('target', '_blank');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@if(ssm.remoteControlEnabled()) {
|
||||
<script>
|
||||
Reveal.configure({
|
||||
keyboard: {
|
||||
@ssm.remoteControlPrevKey(): 'prev',
|
||||
@ssm.remoteControlNextKey(): 'next'
|
||||
}
|
||||
});
|
||||
</script>
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
@(ssm: com.gitpitch.models.SlideshowModel)
|
||||
<style>
|
||||
.centered {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size:1.3em;
|
||||
font-weight: bold;
|
||||
}
|
||||
#gp-logo img {
|
||||
max-height: 3.5em;
|
||||
max-width: none;
|
||||
}
|
||||
@if(ssm.options() != null &&
|
||||
ssm.options().fetchRevealVersion(ssm.params()) == "3.5.0") {
|
||||
.reveal .speaker-notes {
|
||||
background-color: black;
|
||||
opacity : 0.8;
|
||||
}
|
||||
}
|
||||
.reveal .controls {
|
||||
bottom: 20px;
|
||||
}
|
||||
.reveal .slide-number {
|
||||
bottom: 3px !important;
|
||||
font-size: 11px !important;
|
||||
color: gray !important;
|
||||
background-color: inherit !important;
|
||||
}
|
||||
@if(ssm.options() != null &&
|
||||
ssm.options().isLeftLayout(ssm.params())) {
|
||||
.reveal .slides {
|
||||
text-align: left;
|
||||
}
|
||||
.reveal .slides section>* {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
@if(ssm.options() != null &&
|
||||
ssm.options().isRightLayout(ssm.params())) {
|
||||
.reveal .slides {
|
||||
text-align: right;
|
||||
}
|
||||
.reveal .slides section>* {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,15 +0,0 @@
|
|||
@(ssm: com.gitpitch.models.SlideshowModel, deps: com.gitpitch.policies.Dependencies, offline: Boolean, webPrinting: Boolean)
|
||||
<link href="@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/css/reveal.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/css/theme/@ssm.fetchThemeCSS()" rel="stylesheet" type="text/css" id="theme"/>
|
||||
<link href="@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/plugin/title-footer/title-footer-mod.css" rel="stylesheet" type="text/css" id="theme"/>
|
||||
@if(webPrinting) {
|
||||
<link href="@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/css/print/pdf.css" rel="stylesheet" type="text/css"/>
|
||||
} else {
|
||||
<link href="@deps.revealjs(offline, ssm.fetchRevealVersionOverride())/css/print/paper.css" rel="stylesheet" type="text/css"/>
|
||||
}
|
||||
<link href="@deps.highlightjs(offline)/@ssm.fetchHighlightCSS()" rel="stylesheet" type="text/css"/>
|
||||
<link href="@deps.octicons(offline)/octicons.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="@deps.fontawesome(offline)/css/font-awesome.min.css" rel="stylesheet" type="text/css"/>
|
||||
@if(!offline) {
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
@(ssm: com.gitpitch.models.SlideshowModel)
|
||||
@if(ssm.hasThemeOverride()) {
|
||||
<style>
|
||||
@Html(ssm.fetchThemeOverride())
|
||||
</style>
|
||||
}
|
21
build.sbt
|
@ -1,21 +0,0 @@
|
|||
name := """server"""
|
||||
version := "2.0"
|
||||
organization := "com.gitpitch"
|
||||
|
||||
lazy val root = (project in file(".")).enablePlugins(PlayJava, LauncherJarPlugin)
|
||||
|
||||
scalaVersion := "2.11.11"
|
||||
|
||||
libraryDependencies ++= Seq(
|
||||
cache,
|
||||
javaWs,
|
||||
filters
|
||||
)
|
||||
|
||||
libraryDependencies ++= Seq(
|
||||
"com.typesafe.netty" % "netty-reactive-streams-http" % "1.0.6",
|
||||
"com.google.guava" % "guava" % "19.0",
|
||||
"com.google.inject.extensions" % "guice-assistedinject" % "4.0",
|
||||
"org.yaml" % "snakeyaml" % "1.17",
|
||||
"commons-io" % "commons-io" % "2.5"
|
||||
)
|
|
@ -1,510 +0,0 @@
|
|||
# This is the main configuration file for the application.
|
||||
# https://www.playframework.com/documentation/latest/ConfigFile
|
||||
# ~~~~~
|
||||
# Play uses HOCON as its configuration file format. HOCON has a number
|
||||
# of advantages over other config formats, but there are two things that
|
||||
# can be used when modifying settings.
|
||||
#
|
||||
# You can include other configuration files in this main application.conf file:
|
||||
#include "extra-config.conf"
|
||||
#
|
||||
# You can declare variables and substitute for them:
|
||||
#mykey = ${some.value}
|
||||
#
|
||||
# And if an environment variable exists when there is no other subsitution, then
|
||||
# HOCON will fall back to substituting environment variable:
|
||||
#mykey = ${JAVA_HOME}
|
||||
|
||||
## Akka
|
||||
# https://www.playframework.com/documentation/latest/ScalaAkka#Configuration
|
||||
# https://www.playframework.com/documentation/latest/JavaAkka#Configuration
|
||||
# ~~~~~
|
||||
# Play uses Akka internally and exposes Akka Streams and actors in Websockets and
|
||||
# other streaming HTTP responses.
|
||||
akka {
|
||||
# "akka.log-config-on-start" is extraordinarly useful because it log the complete
|
||||
# configuration at INFO level, including defaults and overrides, so it s worth
|
||||
# putting at the very top.
|
||||
#
|
||||
# Put the following in your conf/logback.xml file:
|
||||
#
|
||||
# <logger name="akka.actor" level="INFO" />
|
||||
#
|
||||
# And then uncomment this line to debug the configuration.
|
||||
#
|
||||
#log-config-on-start = true
|
||||
}
|
||||
|
||||
## Secret key
|
||||
# http://www.playframework.com/documentation/latest/ApplicationSecret
|
||||
# ~~~~~
|
||||
# The secret key is used to sign Play's session cookie.
|
||||
# This must be changed for production, but we don't recommend you change it in this file.
|
||||
play.crypto.secret = "changeme"
|
||||
play.crypto.secret = ${?PLAY_CRYPTO_SECRET}
|
||||
|
||||
## Modules
|
||||
# https://www.playframework.com/documentation/latest/Modules
|
||||
# ~~~~~
|
||||
# Control which modules are loaded when Play starts. Note that modules are
|
||||
# the replacement for "GlobalSettings", which are deprecated in 2.5.x.
|
||||
# Please see https://www.playframework.com/documentation/latest/GlobalSettings
|
||||
# for more information.
|
||||
#
|
||||
# You can also extend Play functionality by using one of the publically available
|
||||
# Play modules: https://playframework.com/documentation/latest/ModuleDirectory
|
||||
play.modules {
|
||||
# By default, Play will load any class called Module that is defined
|
||||
# in the root package (the "app" directory), or you can define them
|
||||
# explicitly below.
|
||||
# If there are any built-in modules that you want to disable, you can list them here.
|
||||
#enabled += my.application.Module
|
||||
|
||||
# If there are any built-in modules that you want to disable, you can list them here.
|
||||
#disabled += ""
|
||||
}
|
||||
|
||||
## IDE
|
||||
# https://www.playframework.com/documentation/latest/IDE
|
||||
# ~~~~~
|
||||
# Depending on your IDE, you can add a hyperlink for errors that will jump you
|
||||
# directly to the code location in the IDE in dev mode. The following line makes
|
||||
# use of the IntelliJ IDEA REST interface:
|
||||
#play.editor=http://localhost:63342/api/file/?file=%s&line=%s
|
||||
|
||||
## Internationalisation
|
||||
# https://www.playframework.com/documentation/latest/JavaI18N
|
||||
# https://www.playframework.com/documentation/latest/ScalaI18N
|
||||
# ~~~~~
|
||||
# Play comes with its own i18n settings, which allow the user's preferred language
|
||||
# to map through to internal messages, or allow the language to be stored in a cookie.
|
||||
play.i18n {
|
||||
# The application languages
|
||||
langs = ["en"]
|
||||
|
||||
# Whether the language cookie should be secure or not
|
||||
#langCookieSecure = true
|
||||
|
||||
# Whether the HTTP only attribute of the cookie should be set to true
|
||||
#langCookieHttpOnly = true
|
||||
}
|
||||
|
||||
## Play HTTP settings
|
||||
# ~~~~~
|
||||
play.http {
|
||||
## Router
|
||||
# https://www.playframework.com/documentation/latest/JavaRouting
|
||||
# https://www.playframework.com/documentation/latest/ScalaRouting
|
||||
# ~~~~~
|
||||
# Define the Router object to use for this application.
|
||||
# This router will be looked up first when the application is starting up,
|
||||
# so make sure this is the entry point.
|
||||
# Furthermore, it's assumed your route file is named properly.
|
||||
# So for an application router like `my.application.Router`,
|
||||
# you may need to define a router file `conf/my.application.routes`.
|
||||
# Default to Routes in the root package (aka "apps" folder) (and conf/routes)
|
||||
#router = my.application.Router
|
||||
|
||||
## Action Creator
|
||||
# https://www.playframework.com/documentation/latest/JavaActionCreator
|
||||
# ~~~~~
|
||||
#actionCreator = null
|
||||
|
||||
## ErrorHandler
|
||||
# https://www.playframework.com/documentation/latest/JavaRouting
|
||||
# https://www.playframework.com/documentation/latest/ScalaRouting
|
||||
# ~~~~~
|
||||
# If null, will attempt to load a class called ErrorHandler in the root package,
|
||||
#errorHandler = null
|
||||
|
||||
## Filters
|
||||
# https://www.playframework.com/documentation/latest/ScalaHttpFilters
|
||||
# https://www.playframework.com/documentation/latest/JavaHttpFilters
|
||||
# ~~~~~
|
||||
# Filters run code on every request. They can be used to perform
|
||||
# common logic for all your actions, e.g. adding common headers.
|
||||
# Defaults to "Filters" in the root package (aka "apps" folder)
|
||||
# Alternatively you can explicitly register a class here.
|
||||
#filters = my.application.Filters
|
||||
filters = "com.gitpitch.filters.PitchFilters"
|
||||
|
||||
## Session & Flash
|
||||
# https://www.playframework.com/documentation/latest/JavaSessionFlash
|
||||
# https://www.playframework.com/documentation/latest/ScalaSessionFlash
|
||||
# ~~~~~
|
||||
session {
|
||||
# Sets the cookie to be sent only over HTTPS.
|
||||
#secure = true
|
||||
|
||||
# Sets the cookie to be accessed only by the server.
|
||||
#httpOnly = true
|
||||
|
||||
# Sets the max-age field of the cookie to 5 minutes.
|
||||
# NOTE: this only sets when the browser will discard the cookie. Play will consider any
|
||||
# cookie value with a valid signature to be a valid session forever. To implement a server side session timeout,
|
||||
# you need to put a timestamp in the session and check it at regular intervals to possibly expire it.
|
||||
#maxAge = 300
|
||||
|
||||
# Sets the domain on the session cookie.
|
||||
#domain = "example.com"
|
||||
}
|
||||
|
||||
flash {
|
||||
# Sets the cookie to be sent only over HTTPS.
|
||||
#secure = true
|
||||
|
||||
# Sets the cookie to be accessed only by the server.
|
||||
#httpOnly = true
|
||||
}
|
||||
}
|
||||
|
||||
## Netty Provider
|
||||
# https://www.playframework.com/documentation/latest/SettingsNetty
|
||||
# ~~~~~
|
||||
play.server.netty {
|
||||
# Whether the Netty wire should be logged
|
||||
#log.wire = true
|
||||
|
||||
# If you run Play on Linux, you can use Netty's native socket transport
|
||||
# for higher performance with less garbage.
|
||||
#transport = "native"
|
||||
}
|
||||
|
||||
## WS (HTTP Client)
|
||||
# https://www.playframework.com/documentation/latest/ScalaWS#Configuring-WS
|
||||
# ~~~~~
|
||||
# The HTTP client primarily used for REST APIs. The default client can be
|
||||
# configured directly, but you can also create different client instances
|
||||
# with customized settings. You must enable this by adding to build.sbt:
|
||||
#
|
||||
# libraryDependencies += ws // or javaWs if using java
|
||||
#
|
||||
play.ws {
|
||||
# Sets HTTP requests not to follow 302 requests
|
||||
#followRedirects = false
|
||||
|
||||
# Sets the maximum number of open HTTP connections for the client.
|
||||
#ahc.maxConnectionsTotal = 50
|
||||
|
||||
## WS SSL
|
||||
# https://www.playframework.com/documentation/latest/WsSSL
|
||||
# ~~~~~
|
||||
ssl {
|
||||
# Configuring HTTPS with Play WS does not require programming. You can
|
||||
# set up both trustManager and keyManager for mutual authentication, and
|
||||
# turn on JSSE debugging in development with a reload.
|
||||
#debug.handshake = true
|
||||
#trustManager = {
|
||||
# stores = [
|
||||
# { type = "JKS", path = "exampletrust.jks" }
|
||||
# ]
|
||||
#}
|
||||
}
|
||||
}
|
||||
|
||||
## Cache
|
||||
# https://www.playframework.com/documentation/latest/JavaCache
|
||||
# https://www.playframework.com/documentation/latest/ScalaCache
|
||||
# ~~~~~
|
||||
# Play comes with an integrated cache API that can reduce the operational
|
||||
# overhead of repeated requests. You must enable this by adding to build.sbt:
|
||||
#
|
||||
# libraryDependencies += cache
|
||||
#
|
||||
play.cache {
|
||||
# If you want to bind several caches, you can bind the individually
|
||||
#bindCaches = ["db-cache", "user-cache", "session-cache"]
|
||||
}
|
||||
|
||||
## Filters
|
||||
# https://www.playframework.com/documentation/latest/Filters
|
||||
# ~~~~~
|
||||
# There are a number of built-in filters that can be enabled and configured
|
||||
# to give Play greater security. You must enable this by adding to build.sbt:
|
||||
#
|
||||
# libraryDependencies += filters
|
||||
#
|
||||
play.filters {
|
||||
## CORS filter configuration
|
||||
# https://www.playframework.com/documentation/latest/CorsFilter
|
||||
# ~~~~~
|
||||
# CORS is a protocol that allows web applications to make requests from the browser
|
||||
# across different domains.
|
||||
# NOTE: You MUST apply the CORS configuration before the CSRF filter, as CSRF has
|
||||
# dependencies on CORS settings.
|
||||
cors {
|
||||
# Filter paths by a whitelist of path prefixes
|
||||
#pathPrefixes = ["/some/path", ...]
|
||||
|
||||
# The allowed origins. If null, all origins are allowed.
|
||||
#allowedOrigins = ["http://www.example.com"]
|
||||
allowedOrigins = [".gitpitch.com", "localhost:9000", "127.0.0.1:9000"]
|
||||
|
||||
# The allowed HTTP methods. If null, all methods are allowed
|
||||
#allowedHttpMethods = ["GET", "POST"]
|
||||
}
|
||||
|
||||
## CSRF Filter
|
||||
# https://www.playframework.com/documentation/latest/ScalaCsrf#Applying-a-global-CSRF-filter
|
||||
# https://www.playframework.com/documentation/latest/JavaCsrf#Applying-a-global-CSRF-filter
|
||||
# ~~~~~
|
||||
# Play supports multiple methods for verifying that a request is not a CSRF request.
|
||||
# The primary mechanism is a CSRF token. This token gets placed either in the query string
|
||||
# or body of every form submitted, and also gets placed in the users session.
|
||||
# Play then verifies that both tokens are present and match.
|
||||
csrf {
|
||||
# Sets the cookie to be sent only over HTTPS
|
||||
#cookie.secure = true
|
||||
|
||||
# Defaults to CSRFErrorHandler in the root package.
|
||||
#errorHandler = MyCSRFErrorHandler
|
||||
}
|
||||
|
||||
## Security headers filter configuration
|
||||
# https://www.playframework.com/documentation/latest/SecurityHeaders
|
||||
# ~~~~~
|
||||
# Defines security headers that prevent XSS attacks.
|
||||
# If enabled, then all options are set to the below configuration by default:
|
||||
headers {
|
||||
# The X-Frame-Options header. If null, the header is not set.
|
||||
#frameOptions = "DENY"
|
||||
frameOptions = null
|
||||
|
||||
# The X-XSS-Protection header. If null, the header is not set.
|
||||
#xssProtection = "1; mode=block"
|
||||
|
||||
# The X-Content-Type-Options header. If null, the header is not set.
|
||||
#contentTypeOptions = "nosniff"
|
||||
|
||||
# The X-Permitted-Cross-Domain-Policies header. If null, the header is not set.
|
||||
#permittedCrossDomainPolicies = "master-only"
|
||||
|
||||
# The Content-Security-Policy header. If null, the header is not set.
|
||||
#contentSecurityPolicy = "default-src 'self'"
|
||||
contentSecurityPolicy = null
|
||||
}
|
||||
|
||||
## Allowed hosts filter configuration
|
||||
# https://www.playframework.com/documentation/latest/AllowedHostsFilter
|
||||
# ~~~~~
|
||||
# Play provides a filter that lets you configure which hosts can access your application.
|
||||
# This is useful to prevent cache poisoning attacks.
|
||||
hosts {
|
||||
# Allow requests to example.com, its subdomains, and localhost:9000.
|
||||
allowed = ["localhost", "127.0.0.1", ".local"]
|
||||
}
|
||||
}
|
||||
|
||||
## Evolutions
|
||||
# https://www.playframework.com/documentation/latest/Evolutions
|
||||
# ~~~~~
|
||||
# Evolutions allows database scripts to be automatically run on startup in dev mode
|
||||
# for database migrations. You must enable this by adding to build.sbt:
|
||||
#
|
||||
# libraryDependencies += evolutions
|
||||
#
|
||||
play.evolutions {
|
||||
# You can disable evolutions for a specific datasource if necessary
|
||||
#db.default.enabled = false
|
||||
}
|
||||
|
||||
## Database Connection Pool
|
||||
# https://www.playframework.com/documentation/latest/SettingsJDBC
|
||||
# ~~~~~
|
||||
# Play doesn't require a JDBC database to run, but you can easily enable one.
|
||||
#
|
||||
# libraryDependencies += jdbc
|
||||
#
|
||||
play.db {
|
||||
# The combination of these two settings results in "db.default" as the
|
||||
# default JDBC pool:
|
||||
#config = "db"
|
||||
#default = "default"
|
||||
|
||||
# Play uses HikariCP as the default connection pool. You can override
|
||||
# settings by changing the prototype:
|
||||
prototype {
|
||||
# Sets a fixed JDBC connection pool size of 50
|
||||
#hikaricp.minimumIdle = 50
|
||||
#hikaricp.maximumPoolSize = 50
|
||||
}
|
||||
}
|
||||
|
||||
## JDBC Datasource
|
||||
# https://www.playframework.com/documentation/latest/JavaDatabase
|
||||
# https://www.playframework.com/documentation/latest/ScalaDatabase
|
||||
# ~~~~~
|
||||
# Once JDBC datasource is set up, you can work with several different
|
||||
# database options:
|
||||
#
|
||||
# Slick (Scala preferred option): https://www.playframework.com/documentation/latest/PlaySlick
|
||||
# JPA (Java preferred option): https://playframework.com/documentation/latest/JavaJPA
|
||||
# EBean: https://playframework.com/documentation/latest/JavaEbean
|
||||
# Anorm: https://www.playframework.com/documentation/latest/ScalaAnorm
|
||||
#
|
||||
db {
|
||||
# You can declare as many datasources as you want.
|
||||
# By convention, the default datasource is named `default`
|
||||
|
||||
# https://www.playframework.com/documentation/latest/Developing-with-the-H2-Database
|
||||
#default.driver = org.h2.Driver
|
||||
#default.url = "jdbc:h2:mem:play"
|
||||
#default.username = sa
|
||||
#default.password = ""
|
||||
|
||||
# You can turn on SQL logging for any datasource
|
||||
# https://www.playframework.com/documentation/latest/Highlights25#Logging-SQL-statements
|
||||
#default.logSql=true
|
||||
}
|
||||
|
||||
# GitPitch Custom Configuration
|
||||
gitpitch {
|
||||
|
||||
hostname = "localhost:9000"
|
||||
|
||||
https = false
|
||||
|
||||
storage {
|
||||
#
|
||||
# Directory indicated for this property must exist on disk.
|
||||
# When setting a custom path for this directory you must
|
||||
# specify an absolute path.
|
||||
#
|
||||
home = "/tmp/gitpitch/swap"
|
||||
}
|
||||
|
||||
decktape {
|
||||
#
|
||||
# Absolute path to decktape executable.
|
||||
#
|
||||
home = "/usr/local/bin/decktape"
|
||||
#
|
||||
# Optional args passed to decktape executable.
|
||||
# For example, to workaround Decktape #103 related to
|
||||
# Puppeteer Issue #290, uncomment and use the following:
|
||||
# args = "--no-sandbox"
|
||||
}
|
||||
|
||||
offline {
|
||||
|
||||
prod {
|
||||
fixed {
|
||||
assets {
|
||||
home = "./lib/com.gitpitch.server-2.0-assets.jar"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev {
|
||||
fixed {
|
||||
assets {
|
||||
home = "./public/libs"
|
||||
}
|
||||
}
|
||||
math {
|
||||
assets {
|
||||
home = "./public/libs-math"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependency {
|
||||
revealjs = "3.7.0"
|
||||
bootstrap = "3.3.6"
|
||||
jquery = "2.2.4"
|
||||
fontawesome = "4.7.0"
|
||||
octicons = "3.5.0"
|
||||
highlightjs = "9.13.1"
|
||||
highlight {
|
||||
plugin = false
|
||||
}
|
||||
}
|
||||
|
||||
git {
|
||||
repo {
|
||||
services = [
|
||||
|
||||
{
|
||||
name = "GitHub"
|
||||
type = "github"
|
||||
site = "https://github.com/"
|
||||
apibase = "https://api.github.com/"
|
||||
// apitoken = "token your-github-access-token-here"
|
||||
apitokenheader = "Authorization"
|
||||
rawbase = "https://raw.githubusercontent.com/"
|
||||
gistbase = "https://gist.githubusercontent.com/"
|
||||
branchdelim = "~"
|
||||
default = "true"
|
||||
}
|
||||
{
|
||||
name = "GitLab"
|
||||
type = "gitlab"
|
||||
site = "https://gitlab.com/"
|
||||
apibase = "https://gitlab.com/api/v4/"
|
||||
// apitoken = "your-gitlab-access-token-here"
|
||||
apitokenheader = "PRIVATE-TOKEN"
|
||||
rawbase = "https://gitlab.com/"
|
||||
branchdelim = "~"
|
||||
default = "false"
|
||||
}
|
||||
{
|
||||
name = "Bitbucket"
|
||||
type = "bitbucket"
|
||||
site = "https://bitbucket.org/"
|
||||
apibase = "https://api.bitbucket.org/2.0/"
|
||||
// apitoken = "your-bitbucket-access-token-here"
|
||||
apitokenheader = "Authorization"
|
||||
rawbase = "https://bitbucket.org/"
|
||||
branchdelim = "~"
|
||||
default = "false"
|
||||
}
|
||||
{
|
||||
name = "Gitea"
|
||||
type = "gitea"
|
||||
site = "https://localhost:3000/"
|
||||
apibase = "http://localhost:3000/api/v1/"
|
||||
// apitoken = "token your-gitea-app-token-here"
|
||||
apitokenheader = "Authorization"
|
||||
rawbase = "http://localhost:3000/"
|
||||
branchdelim = "~"
|
||||
default = "false"
|
||||
}
|
||||
{
|
||||
name = "Gogs"
|
||||
type = "gogs"
|
||||
site = "https://localhost:3000/"
|
||||
apibase = "http://localhost:3000/api/v1/"
|
||||
apitoken = "token your-gitea-app-token-here"
|
||||
apitokenheader = "Authorization"
|
||||
rawbase = "http://localhost:3000/"
|
||||
branchdelim = "~"
|
||||
default = "false"
|
||||
}
|
||||
{
|
||||
name = "GitBucket"
|
||||
type = "gitbucket"
|
||||
site = "http://localhost:8080/"
|
||||
apibase = "http://localhost:8080/api/v3/"
|
||||
// apitoken = "token your-gitbucket-access-token-here"
|
||||
apitokenheader = "Authorization"
|
||||
rawbase = "http://localhost:8080/"
|
||||
branchdelim = "~"
|
||||
default = "false"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
revealjs {
|
||||
themes = ["black", "moon", "night", "beige", "sky", "white"]
|
||||
}
|
||||
|
||||
google {
|
||||
analytics {
|
||||
// token = "your-google-analytics-token"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
<!-- https://www.playframework.com/documentation/latest/SettingsLogger -->
|
||||
<configuration>
|
||||
|
||||
<conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel"/>
|
||||
|
||||
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>${application.home:-.}/logs/server.log</file>
|
||||
<encoder>
|
||||
<pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%date %thread %coloredLevel %logger{15} - %message%n%xException{10}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<appender-ref ref="FILE"/>
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</appender>
|
||||
|
||||
<logger name="play" level="INFO"/>
|
||||
<logger name="com.gitpitch.controllers" level="DEBUG" additivity="false">
|
||||
<appender-ref ref="ASYNCSTDOUT"/>
|
||||
</logger>
|
||||
<logger name="com.gitpitch.services" level="DEBUG" additivity="false">
|
||||
<appender-ref ref="ASYNCSTDOUT"/>
|
||||
</logger>
|
||||
<logger name="com.gitpitch.models" level="DEBUG" additivity="false">
|
||||
<appender-ref ref="ASYNCSTDOUT"/>
|
||||
</logger>
|
||||
<logger name="com.gitpitch.filters" level="DEBUG" additivity="false">
|
||||
<appender-ref ref="ASYNCSTDOUT"/>
|
||||
</logger>
|
||||
<logger name="com.gitpitch.git" level="DEBUG" additivity="false">
|
||||
<appender-ref ref="ASYNCSTDOUT"/>
|
||||
</logger>
|
||||
<logger name="com.gitpitch.utils" level="DEBUG" additivity="false">
|
||||
<appender-ref ref="ASYNCSTDOUT"/>
|
||||
</logger>
|
||||
|
||||
<!-- Off these ones as they are annoying, and anyway we manage configuration ourselves -->
|
||||
<logger name="com.avaje.ebean.config.PropertyMapLoader" level="OFF"/>
|
||||
<logger name="com.avaje.ebeaninternal.server.core.XmlConfigLoader" level="OFF"/>
|
||||
<logger name="com.avaje.ebeaninternal.server.lib.BackgroundThread" level="OFF"/>
|
||||
<logger name="com.gargoylesoftware.htmlunit.javascript" level="OFF"/>
|
||||
|
||||
<root level="WARN">
|
||||
<appender-ref ref="ASYNCFILE"/>
|
||||
<appender-ref ref="ASYNCSTDOUT"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
48
conf/routes
|
@ -1,48 +0,0 @@
|
|||
# Routes
|
||||
# This file defines all application routes (Higher priority routes first)
|
||||
# ~~~~
|
||||
|
||||
# Map static resources from the /public folder to the /assets URL path
|
||||
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
|
||||
|
||||
# Serve GitPitch markdown template bundles as zip archives.
|
||||
GET /template/download/:template com.gitpitch.controllers.PitchController.template(template:String)
|
||||
|
||||
# Serve GitPitch oEmbed provider responses.
|
||||
GET /pitchme/oembed com.gitpitch.controllers.PitchController.oembed(url:String, format:String ?= null, width:String ?= null, height:String ?= null, maxwidth:String ?= null, maxheight:String ?= null, referrer:String ?= null)
|
||||
|
||||
# Serve GitPitch GIST iFrame for {gid}.
|
||||
GET /pitchme/gist/:gid com.gitpitch.controllers.PitchController.gist(gid:String)
|
||||
|
||||
# Serve GitPitch Home Side Panel
|
||||
GET /pitchme/home/:grs/:user/:repo/:b/:t com.gitpitch.controllers.PitchController.home(grs:String, user:String, repo:String, b:String, t:String, p:String ?= null, offline:String ?= null)
|
||||
|
||||
# Serve GitPitch Git (GRS) Side Panel
|
||||
GET /pitchme/git/:grs/:user/:repo/:b/:t com.gitpitch.controllers.PitchController.git(grs:String, user:String, repo:String, b:String, t:String, p:String ?= null, offline:String ?= null)
|
||||
|
||||
# Serve GitPitch Themes Side Panel
|
||||
GET /pitchme/themes/:grs/:user/:repo/:b/:t com.gitpitch.controllers.PitchController.themes(grs:String, user:String, repo:String, b:String, t:String, p:String ?= null, offline:String ?= null)
|
||||
|
||||
# Serve PITCHME.pdf.
|
||||
GET /pitchme/print/:grs/:user/:repo/:b/:t/PITCHME.pdf com.gitpitch.controllers.PitchController.print(grs:String, user:String, repo:String, b:String, t:String, p:String ?= null, n:String ?= null)
|
||||
|
||||
# Serve PITCHME.zip.
|
||||
GET /pitchme/offline/:grs/:user/:repo/:b/:t/PITCHME.zip com.gitpitch.controllers.PitchController.offline(grs:String, user:String, repo:String, b:String, t:String, p:String ?= null, n:String ?= null)
|
||||
|
||||
# Redirect to GitHub OAuth Access Request
|
||||
# GET /pitchme/authreq com.gitpitch.controllers.AuthController.authreq()
|
||||
|
||||
# Handle GitHub OAuth Callback
|
||||
# GET /pitchme/authorized com.gitpitch.controllers.AuthController.authorized(code:String ?= null, state:String ?= null)
|
||||
|
||||
# Serve PITCHME.md markdown.
|
||||
GET /pitchme/markdown/:grs/:user/:repo/:b/PITCHME.md com.gitpitch.controllers.PitchController.markdown(grs:String, user:String, repo:String, b:String, p:String ?= null)
|
||||
|
||||
# Serve PITCHME.md presentation page.
|
||||
GET /:user/:repo/:b com.gitpitch.controllers.PitchController.slideshow(user:String, repo:String, b:String, grs:String ?= null, t:String ?= null, p:String?= null, n:String ?= null, offline:String ?= null, fragments:String ?= null, `print-pdf`:String ?= null)
|
||||
|
||||
# Serve PITCHME.md presentation page, short URI format.
|
||||
GET /:user/:repo com.gitpitch.controllers.PitchController.slideshow(user:String, repo:String, b:String ?= null, grs:String ?= null, t:String ?= null, p:String?= null, n:String ?= null, offline:String ?= null, fragments:String ?= null, `print-pdf`:String ?= null)
|
||||
|
||||
# Catch-all route redirect to website.
|
||||
GET /*path com.gitpitch.controllers.PitchController.catchall(path:String)
|
5
deps/package.json
vendored
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"decktape": "^2.6.1"
|
||||
}
|
||||
}
|
0
docs/.nojekyll
Normal file
4
docs/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
# GitPitch 4.0
|
||||
|
||||
!> Slide Decks for Tech Conferences, Training, Developer Advocates, and Educators.
|
||||
|
BIN
docs/_images/charts-bar-sample.jpg
Normal file
After Width: | Height: | Size: 163 KiB |
BIN
docs/_images/charts-line-sample.jpg
Normal file
After Width: | Height: | Size: 152 KiB |
BIN
docs/_images/charts-radar-sample.jpg
Normal file
After Width: | Height: | Size: 144 KiB |
BIN
docs/_images/code-font-fc.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
docs/_images/code-font-inconsolata.png
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
docs/_images/code-font-scp.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
docs/_images/code-font-vm.png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
docs/_images/code-font-vmi.png
Normal file
After Width: | Height: | Size: 87 KiB |
BIN
docs/_images/code-highlighting-agate.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
docs/_images/code-highlighting-github.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
docs/_images/code-highlighting-hybrid.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
docs/_images/code-highlighting-ir-black.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
docs/_images/code-highlighting-mono-blue.png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
docs/_images/code-highlighting-solarized-light.png
Normal file
After Width: | Height: | Size: 65 KiB |