This commit is contained in:
Dane Everitt 2020-04-25 19:30:57 -07:00
commit 11461e29a0
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
49 changed files with 6105 additions and 4475 deletions

View File

@ -2,7 +2,23 @@ module.exports = {
base: '/',
title: 'Pterodactyl',
description: 'The open-source server management solution.',
ga: 'UA-87324178-1',
plugins: [
['@vuepress/google-analytics', {
ga: 'UA-12345678-9'
},],
['@vuepress/search', {
searchMaxSuggestions: 10
}],
['vuepress-plugin-container', {
type: 'warning',
}],
['vuepress-plugin-container', {
type: 'tip',
}],
['vuepress-plugin-container', {
type: 'danger',
}],
],
configureWebpack: {
serve: {
hot: {
@ -111,24 +127,63 @@ module.exports = {
{
title: 'Panel',
collapsable: false,
children: [
'/panel/getting_started',
'/panel/webserver_configuration',
'/panel/upgrading',
'/panel/configuration',
'/panel/troubleshooting',
path: '/panel/',
currentVersion: '0.7',
versions: [
{
name: '0.7',
status: 'stable',
children: [
'/getting_started',
'/webserver_configuration',
'/upgrading',
'/configuration',
'/troubleshooting',
]
},
{
name: '1.0',
status: 'beta',
children: [
'/getting_started',
'/webserver_configuration'
]
}
]
},
{
title: 'Daemon',
collapsable: false,
children: [
'/daemon/installing',
'/daemon/upgrading',
'/daemon/configuration',
'/daemon/kernel_modifications',
'/daemon/debian_8_docker',
'/daemon/standalone_sftp',
path: '/daemon/',
currentVersion: '0.6',
versions: [
{
name: '0.6',
children: [
'/installing',
'/upgrading',
'/configuration',
'/kernel_modifications',
'/debian_8_docker',
'/standalone_sftp',
]
}
]
},
{
title: 'Wings',
collapsable: false,
path: '/wings/',
currentVersion: '',
versions: [
{
name: '1.0',
status: 'beta',
children: [
'/installing',
'/upgrading',
]
}
]
},
{

41
.vuepress/enhanceApp.js Normal file
View File

@ -0,0 +1,41 @@
export default ({
Vue, // the version of Vue being used in the VuePress app
options, // the options for the root Vue instance
router, // the router instance for the app
siteData, // site metadata
isServer // is this enhancement applied in server-rendering or client
}) => {
findVersionedPaths(siteData.themeConfig.sidebar).forEach(vp => {
router.addRoutes(
router.options.routes.map(route => {
if (route.path.startsWith(vp.path + vp.currentVersion)) {
return [
{
path: route.path.replace(vp.currentVersion, "current"),
redirect: route.path
}, {
path: route.path.replace(vp.currentVersion + "/", ""),
redirect: route.path
}
]
}
return undefined
}).filter(x => x).flat()
)
})
}
function findVersionedPaths(paths) {
return Object.entries(paths).map(([path, children]) => {
return children
.filter(child => Array.isArray(child.versions))
.map(child => ({ ...child, path: pathJoin(path, child.path) }))
}).flat()
}
// https://stackoverflow.com/a/29855282/4430124
function pathJoin(...parts) {
var separator = '/';
var replace = new RegExp(separator + '{1,}', 'g');
return parts.join(separator).replace(replace, separator);
}

View File

@ -4,7 +4,7 @@
<div class="container z-10">
<div class="text-center">
<div>
<img class="max-w-xl w-full" src="https://cdn.pterodactyl.io/logos/new/pterodactyl_logo_transparent.png" alt="Pterodactyl">
<img class="max-w-xl w-full inline-block" src="https://cdn.pterodactyl.io/logos/new/pterodactyl_logo_transparent.png" alt="Pterodactyl">
</div>
<div class="mt-4">
<a class="btn hidden md:inline-block" href="https://demo.pterodactyl.io" target="_blank" rel="nofollow noopener">Demo</a>
@ -22,7 +22,7 @@
while exposing a beautiful and intuitive UI to administrators and users. Stop wasting time fiddling
with other systems &mdash; make game servers a first class citizen on your platform.
</h3>
<img class="max-w-lg w-full m-4" :src="$withBase('frontpage/mockup-macbook-grey.png')"></div>
<img class="max-w-lg w-full m-4 inline-block" :src="$withBase('frontpage/mockup-macbook-grey.png')"></div>
</div>
<div class="section bg-blue text-grey-lightest">
<div class="container text-center">
@ -116,7 +116,7 @@
</a>
</div>
</div>
<div class="footer">MIT Licensed | Copyright © 2015 - 2019 Dane Everitt & Contributors.</div>
<div class="footer">MIT Licensed | Copyright © 2015 - 2020 Dane Everitt & Contributors.</div>
</div>
</div>
</div>

View File

@ -1,133 +1,135 @@
<template>
<div class="theme-container"
:class="pageClasses"
@touchstart="onTouchStart"
@touchend="onTouchEnd">
<Navbar v-if="shouldShowNavbar" @toggle-sidebar="toggleSidebar"/>
<div class="sidebar-mask" @click="toggleSidebar(false)"></div>
<Sidebar :items="sidebarItems" @toggle-sidebar="toggleSidebar">
<slot name="sidebar-top" slot="top"/>
<slot name="sidebar-bottom" slot="bottom"/>
</Sidebar>
<div class="custom-layout" v-if="$page.frontmatter.layout">
<component :is="$page.frontmatter.layout"/>
</div>
<Home v-else-if="$page.frontmatter.home"/>
<Page v-else :sidebar-items="sidebarItems">
<slot name="page-top" slot="top"/>
<slot name="page-bottom" slot="bottom"/>
</Page>
<div
class="theme-container"
:class="pageClasses"
@touchstart="onTouchStart"
@touchend="onTouchEnd"
>
<Navbar v-if="shouldShowNavbar" @toggle-sidebar="toggleSidebar" />
<div class="sidebar-mask" @click="toggleSidebar(false)"></div>
<Sidebar :items="sidebarItems" @toggle-sidebar="toggleSidebar">
<slot name="sidebar-top" slot="top" />
<slot name="sidebar-bottom" slot="bottom" />
</Sidebar>
<div class="custom-layout" v-if="$page.frontmatter.layout">
<component :is="$page.frontmatter.layout" />
</div>
<Home v-else-if="$page.frontmatter.home" />
<Page v-else :sidebar-items="sidebarItems">
<slot name="page-top" slot="top" />
<slot name="page-bottom" slot="bottom" />
</Page>
</div>
</template>
<script>
import Vue from 'vue';
import nprogress from 'nprogress';
import Home from './Home.vue';
import Navbar from './Navbar.vue';
import Page from './Page.vue';
import Sidebar from './Sidebar.vue';
import { resolveSidebarItems } from './util';
import Vue from "vue";
import nprogress from "nprogress";
import Home from "./Home.vue";
import Navbar from "./Navbar.vue";
import Page from "./Page.vue";
import Sidebar from "./Sidebar.vue";
import { resolveSidebarItems } from "./util";
export default {
components: { Home, Page, Sidebar, Navbar },
data() {
return {
isSidebarOpen: false
};
},
computed: {
shouldShowNavbar() {
const { themeConfig } = this.$site;
const { frontmatter } = this.$page;
if (
frontmatter.navbar === false ||
themeConfig.navbar === false) {
return false;
}
return (
this.$title ||
themeConfig.logo ||
themeConfig.repo ||
themeConfig.nav ||
this.$themeLocaleConfig.nav
);
},
shouldShowSidebar() {
const { frontmatter } = this.$page;
return (
! frontmatter.layout &&
! frontmatter.home &&
frontmatter.sidebar !== false &&
this.sidebarItems.length
);
},
sidebarItems() {
return resolveSidebarItems(
this.$page,
this.$route,
this.$site,
this.$localePath
);
},
pageClasses() {
const userPageClass = this.$page.frontmatter.pageClass;
return [
{
'no-navbar': ! this.shouldShowNavbar,
'sidebar-open': this.isSidebarOpen,
'no-sidebar': ! this.shouldShowSidebar
},
userPageClass
];
}
},
mounted() {
window.addEventListener('scroll', this.onScroll);
// configure progress bar
nprogress.configure({ showSpinner: false });
this.$router.beforeEach((to, from, next) => {
if (to.path !== from.path && ! Vue.component(to.name)) {
nprogress.start();
}
next();
});
this.$router.afterEach(() => {
nprogress.done();
this.isSidebarOpen = false;
});
},
methods: {
toggleSidebar(to) {
this.isSidebarOpen = typeof to === 'boolean' ? to : ! this.isSidebarOpen;
},
// side swipe
onTouchStart(e) {
this.touchStart = {
x: e.changedTouches[0].clientX,
y: e.changedTouches[0].clientY
};
},
onTouchEnd(e) {
const dx = e.changedTouches[0].clientX - this.touchStart.x;
const dy = e.changedTouches[0].clientY - this.touchStart.y;
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
if (dx > 0 && this.touchStart.x <= 80) {
this.toggleSidebar(true);
} else {
this.toggleSidebar(false);
}
}
}
}
export default {
components: { Home, Page, Sidebar, Navbar },
data() {
return {
isSidebarOpen: false
};
},
computed: {
shouldShowNavbar() {
const { themeConfig } = this.$site;
const { frontmatter } = this.$page;
if (frontmatter.navbar === false || themeConfig.navbar === false) {
return false;
}
return (
this.$title ||
themeConfig.logo ||
themeConfig.repo ||
themeConfig.nav ||
this.$themeLocaleConfig.nav
);
},
shouldShowSidebar() {
const { frontmatter } = this.$page;
return (
!frontmatter.layout &&
!frontmatter.home &&
frontmatter.sidebar !== false &&
this.sidebarItems.length
);
},
sidebarItems() {
return resolveSidebarItems(
this.$page,
this.$route,
this.$site,
this.$localePath
);
},
pageClasses() {
const userPageClass = this.$page.frontmatter.pageClass;
return [
{
"no-navbar": !this.shouldShowNavbar,
"sidebar-open": this.isSidebarOpen,
"no-sidebar": !this.shouldShowSidebar
},
userPageClass
];
}
},
mounted() {
window.addEventListener("scroll", this.onScroll);
// configure progress bar
nprogress.configure({ showSpinner: false });
this.$router.beforeEach((to, from, next) => {
if (to.path !== from.path && !Vue.component(to.name)) {
nprogress.start();
}
next();
});
this.$router.afterEach(() => {
nprogress.done();
this.isSidebarOpen = false;
});
},
methods: {
toggleSidebar(to) {
this.isSidebarOpen = typeof to === "boolean" ? to : !this.isSidebarOpen;
},
// side swipe
onTouchStart(e) {
this.touchStart = {
x: e.changedTouches[0].clientX,
y: e.changedTouches[0].clientY
};
},
onTouchEnd(e) {
const dx = e.changedTouches[0].clientX - this.touchStart.x;
const dy = e.changedTouches[0].clientY - this.touchStart.y;
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
if (dx > 0 && this.touchStart.x <= 80) {
this.toggleSidebar(true);
} else {
this.toggleSidebar(false);
}
}
}
}
};
</script>
<style src="prismjs/themes/prism-tomorrow.css"></style>
<style src="./styles/main.css" lang="postcss"></style>
<style lang="postcss">
@import "./styles/main.css";
</style>

View File

@ -1,42 +1,35 @@
<template>
<header class="nav">
<SidebarButton class="block md:hidden flex-no-shrink" @toggle-sidebar="$emit('toggle-sidebar')"/>
<div class="logo-container">
<router-link :to="$localePath" class="home-link">
<img class="logo"
v-if="$site.themeConfig.logo"
:src="$withBase($site.themeConfig.logo)">
<span class="site-name hidden md:inline"
v-if="$siteTitle"
:class="{ 'can-hide': $site.themeConfig.logo }">
{{ $siteTitle }}
</span>
</router-link>
</div>
<div class="w-full">
<div class="flex">
<SearchBox/>
<NavLinks class="hidden md:flex"/>
</div>
</div>
</header>
<header class="nav">
<SidebarButton
class="block md:hidden flex-no-shrink"
@toggle-sidebar="$emit('toggle-sidebar')"
/>
<div class="logo-container">
<router-link :to="$localePath" class="home-link">
<img class="logo" v-if="$site.themeConfig.logo" :src="$withBase($site.themeConfig.logo)" />
<span
class="site-name hidden md:inline"
v-if="$siteTitle"
:class="{ 'can-hide': $site.themeConfig.logo }"
>{{ $siteTitle }}</span>
</router-link>
</div>
<div class="w-full">
<div class="flex">
<SearchBox />
<NavLinks class="hidden md:flex" />
</div>
</div>
</header>
</template>
<script>
import SidebarButton from './SidebarButton.vue';
import AlgoliaSearchBox from '@AlgoliaSearchBox';
import SearchBox from './SearchBox.vue';
import NavLinks from './NavLinks.vue';
import SidebarButton from "./SidebarButton.vue";
import SearchBox from "./SearchBox.vue";
import NavLinks from "./NavLinks.vue";
export default {
components: { SidebarButton, NavLinks, SearchBox, AlgoliaSearchBox },
computed: {
algolia() {
return this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {};
},
isAlgoliaSearch() {
return this.algolia && this.algolia.apiKey && this.algolia.indexName;
}
}
};
export default {
components: { SidebarButton, NavLinks, SearchBox },
computed: {}
};
</script>

View File

@ -1,156 +1,155 @@
<template>
<div class="page">
<slot name="top"/>
<Content :custom="false"/>
<div class="page-edit">
<div class="edit-link" v-if="editLink">
<a :href="editLink" target="_blank" rel="noopener noreferrer">{{ editLinkText }}</a>
<OutboundLink/>
</div>
<div class="last-updated" v-if="lastUpdated">
<span class="prefix">{{ lastUpdatedText }}: </span>
<span class="time">{{ lastUpdated }}</span>
</div>
</div>
<div class="page-nav" v-if="prev || next">
<p class="inner"></p>
<div class="prev">
<span v-if="prev">
<router-link v-if="prev" :to="prev.path">{{ prev.title || prev.path }}</router-link>
</span>
</div>
<div class="next">
<span v-if="next">
<router-link v-if="next" :to="next.path">{{ next.title || next.path }}</router-link>
</span>
</div>
</div>
<slot name="bottom"/>
<div class="page">
<slot name="top" />
<Content class="content" :custom="false" />
<div class="page-edit">
<div class="edit-link" v-if="editLink">
<a :href="editLink" target="_blank" rel="noopener noreferrer">{{ editLinkText }}</a>
<OutboundLink />
</div>
<div class="last-updated" v-if="lastUpdated">
<span class="prefix">{{ lastUpdatedText }}:</span>
<span class="time">{{ lastUpdated }}</span>
</div>
</div>
<div class="page-nav" v-if="prev || next">
<p class="inner"></p>
<div class="prev">
<span v-if="prev">
<router-link v-if="prev" :to="prev.path">{{ prev.title || prev.path }}</router-link>
</span>
</div>
<div class="next">
<span v-if="next">
<router-link v-if="next" :to="next.path">{{ next.title || next.path }}</router-link>
</span>
</div>
</div>
<slot name="bottom" />
</div>
</template>
<script>
import { resolvePage, normalize, outboundRE, endingSlashRE } from './util';
import { resolvePage, normalize, outboundRE, endingSlashRE } from "./util";
export default {
props: ['sidebarItems'],
computed: {
lastUpdated() {
if (this.$page.lastUpdated) {
return new Date(this.$page.lastUpdated).toLocaleString(this.$lang);
}
},
lastUpdatedText() {
if (typeof this.$themeLocaleConfig.lastUpdated === 'string') {
return this.$themeLocaleConfig.lastUpdated;
}
if (typeof this.$site.themeConfig.lastUpdated === 'string') {
return this.$site.themeConfig.lastUpdated;
}
return 'Last Updated';
},
prev() {
const prev = this.$page.frontmatter.prev;
if (prev === false) {
return;
} else if (prev) {
return resolvePage(this.$site.pages, prev, this.$route.path);
} else {
return resolvePrev(this.$page, this.sidebarItems);
}
},
next() {
const next = this.$page.frontmatter.next;
if (next === false) {
return;
} else if (next) {
return resolvePage(this.$site.pages, next, this.$route.path);
} else {
return resolveNext(this.$page, this.sidebarItems);
}
},
editLink() {
if (this.$page.frontmatter.editLink === false) {
return;
}
const {
repo,
editLinks,
docsDir = '',
docsBranch = 'master',
docsRepo = repo
} = this.$site.themeConfig;
export default {
props: ["sidebarItems"],
computed: {
lastUpdated() {
if (this.$page.lastUpdated) {
return new Date(this.$page.lastUpdated).toLocaleString(this.$lang);
}
},
lastUpdatedText() {
if (typeof this.$themeLocaleConfig.lastUpdated === "string") {
return this.$themeLocaleConfig.lastUpdated;
}
if (typeof this.$site.themeConfig.lastUpdated === "string") {
return this.$site.themeConfig.lastUpdated;
}
return "Last Updated";
},
prev() {
const prev = this.$page.frontmatter.prev;
if (prev === false) {
return;
} else if (prev) {
return resolvePage(this.$site.pages, prev, this.$route.path);
} else {
return resolvePrev(this.$page, this.sidebarItems);
}
},
next() {
const next = this.$page.frontmatter.next;
if (next === false) {
return;
} else if (next) {
return resolvePage(this.$site.pages, next, this.$route.path);
} else {
return resolveNext(this.$page, this.sidebarItems);
}
},
editLink() {
if (this.$page.frontmatter.editLink === false) {
return;
}
const {
repo,
editLinks,
docsDir = "",
docsBranch = "master",
docsRepo = repo
} = this.$site.themeConfig;
let path = normalize(this.$page.path);
if (endingSlashRE.test(path)) {
path += 'README.md';
} else {
path += '.md';
}
if (docsRepo && editLinks) {
return this.createEditLink(repo, docsRepo, docsDir, docsBranch, path);
}
},
editLinkText() {
return (
this.$themeLocaleConfig.editLinkText ||
this.$site.themeConfig.editLinkText ||
`Edit this page`
);
}
},
methods: {
createEditLink(repo, docsRepo, docsDir, docsBranch, path) {
const bitbucket = /bitbucket.org/;
if (bitbucket.test(repo)) {
const base = outboundRE.test(docsRepo)
? docsRepo
: repo;
return (
base.replace(endingSlashRE, '') +
`/${docsBranch}` +
(docsDir ? '/' + docsDir.replace(endingSlashRE, '') : '') +
path +
`?mode=edit&spa=0&at=${docsBranch}&fileviewer=file-view-default`
);
}
const base = outboundRE.test(docsRepo)
? docsRepo
: `https://github.com/${docsRepo}`;
return (
base.replace(endingSlashRE, '') +
`/edit/${docsBranch}` +
(docsDir ? '/' + docsDir.replace(endingSlashRE, '') : '') +
path
);
}
}
};
function resolvePrev(page, items) {
return find(page, items, - 1);
let path = normalize(this.$page.path);
if (endingSlashRE.test(path)) {
path += "README.md";
} else {
path += ".md";
}
if (docsRepo && editLinks) {
return this.createEditLink(repo, docsRepo, docsDir, docsBranch, path);
}
},
editLinkText() {
return (
this.$themeLocaleConfig.editLinkText ||
this.$site.themeConfig.editLinkText ||
`Edit this page`
);
}
},
methods: {
createEditLink(repo, docsRepo, docsDir, docsBranch, path) {
const bitbucket = /bitbucket.org/;
if (bitbucket.test(repo)) {
const base = outboundRE.test(docsRepo) ? docsRepo : repo;
return (
base.replace(endingSlashRE, "") +
`/${docsBranch}` +
(docsDir ? "/" + docsDir.replace(endingSlashRE, "") : "") +
path +
`?mode=edit&spa=0&at=${docsBranch}&fileviewer=file-view-default`
);
}
function resolveNext(page, items) {
return find(page, items, 1);
}
const base = outboundRE.test(docsRepo)
? docsRepo
: `https://github.com/${docsRepo}`;
function find(page, items, offset) {
const res = [];
items.forEach(item => {
if (item.type === 'group') {
res.push(...item.children || []);
} else {
res.push(item);
}
});
for (let i = 0; i < res.length; i ++) {
const cur = res[i];
if (cur.type === 'page' && cur.path === page.path) {
return res[i + offset];
}
}
return (
base.replace(endingSlashRE, "") +
`/edit/${docsBranch}` +
(docsDir ? "/" + docsDir.replace(endingSlashRE, "") : "") +
path
);
}
}
};
function resolvePrev(page, items) {
return find(page, items, -1);
}
function resolveNext(page, items) {
return find(page, items, 1);
}
function find(page, items, offset) {
const res = [];
items.forEach(item => {
if (item.type === "group") {
res.push(...(item.children || []));
} else {
res.push(item);
}
});
for (let i = 0; i < res.length; i++) {
const cur = res[i];
if (cur.type === "page" && cur.path === page.path) {
return res[i + offset];
}
}
}
</script>

View File

@ -1,137 +1,137 @@
<template>
<div class="search-box">
<input
@input="query = $event.target.value"
aria-label="Search"
:value="query"
placeholder="Search"
autocomplete="off"
spellcheck="false"
@focus="focused = true"
@blur="focused = false"
@keyup.enter="go(focusIndex)"
@keyup.up="onUp"
@keyup.down="onDown">
<div class="suggestion-container" v-if="showSuggestions" @mouseleave="unfocus">
<div class="suggestion-padding"></div>
<ul class="suggestions" :class="{ 'align-right': alignRight }">
<li class="suggestion" v-for="(s, i) in suggestions"
:class="{ focused: i === focusIndex }"
@mousedown="go(i)"
@mouseenter="focus(i)">
<a :href="s.path" @click.prevent>
<span class="page-title">{{ s.title || s.path }}</span>
<span v-if="s.header" class="header">&gt; {{ s.header.title }}</span>
</a>
</li>
</ul>
</div>
<div class="search-box">
<input
@input="query = $event.target.value"
aria-label="Search"
:value="query"
placeholder="Search"
autocomplete="off"
spellcheck="false"
@focus="focused = true"
@blur="focused = false"
@keyup.enter="go(focusIndex)"
@keyup.up="onUp"
@keyup.down="onDown"
/>
<div class="suggestion-container" v-if="showSuggestions" @mouseleave="unfocus">
<div class="suggestion-padding"></div>
<ul class="suggestions" :class="{ 'align-right': alignRight }">
<li
class="suggestion"
v-for="(s, i) in suggestions"
:class="{ focused: i === focusIndex }"
@mousedown="go(i)"
@mouseenter="focus(i)"
>
<a :href="s.path" @click.prevent>
<span class="page-title">{{ s.title || s.path }}</span>
<span v-if="s.header" class="header">&gt; {{ s.header.title }}</span>
</a>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data() {
return {
query: '',
focused: false,
focusIndex: 0
};
},
computed: {
showSuggestions() {
return (
this.focused &&
this.suggestions &&
this.suggestions.length
);
},
suggestions() {
const query = this.query.trim().toLowerCase();
if (! query) {
return;
}
const { pages, themeConfig } = this.$site;
const max = themeConfig.searchMaxSuggestions || 5;
const localePath = this.$localePath;
const matches = item => (
item.title &&
item.title.toLowerCase().indexOf(query) > - 1
);
const res = [];
for (let i = 0; i < pages.length; i ++) {
if (res.length >= max) break;
const p = pages[i];
// filter out results that do not match current locale
if (this.getPageLocalePath(p) !== localePath) {
continue;
}
if (matches(p)) {
res.push(p);
} else if (p.headers) {
for (let j = 0; j < p.headers.length; j ++) {
if (res.length >= max) break;
const h = p.headers[j];
if (matches(h)) {
res.push(Object.assign({}, p, {
path: p.path + '#' + h.slug,
header: h
}));
}
}
}
}
return res;
},
// make suggestions align right when there are not enough items
alignRight() {
const navCount = (this.$site.themeConfig.nav || []).length;
const repo = this.$site.repo ? 1 : 0;
return navCount + repo <= 2;
}
},
methods: {
getPageLocalePath(page) {
for (const localePath in this.$site.locales || {}) {
if (localePath !== '/' && page.path.indexOf(localePath) === 0) {
return localePath;
}
}
return '/';
},
onUp() {
if (this.showSuggestions) {
if (this.focusIndex > 0) {
this.focusIndex --;
} else {
this.focusIndex = this.suggestions.length - 1;
}
}
},
onDown() {
if (this.showSuggestions) {
if (this.focusIndex < this.suggestions.length - 1) {
this.focusIndex ++;
} else {
this.focusIndex = 0;
}
}
},
go(i) {
if (! this.showSuggestions) {
return;
}
this.$router.push(this.suggestions[i].path);
this.query = '';
this.focusIndex = 0;
},
focus(i) {
this.focusIndex = i;
},
unfocus() {
this.focusIndex = - 1;
}
}
export default {
data() {
return {
query: "",
focused: false,
focusIndex: 0
};
},
computed: {
showSuggestions() {
return this.focused && this.suggestions && this.suggestions.length;
},
suggestions() {
const query = this.query.trim().toLowerCase();
if (!query) {
return;
}
const { pages, themeConfig } = this.$site;
const max = themeConfig.searchMaxSuggestions || 5;
const localePath = this.$localePath;
const matches = item =>
item.title && item.title.toLowerCase().indexOf(query) > -1;
const res = [];
for (let i = 0; i < pages.length; i++) {
if (res.length >= max) break;
const p = pages[i];
// filter out results that do not match current locale
if (this.getPageLocalePath(p) !== localePath) {
continue;
}
if (matches(p)) {
res.push(p);
} else if (p.headers) {
for (let j = 0; j < p.headers.length; j++) {
if (res.length >= max) break;
const h = p.headers[j];
if (matches(h)) {
res.push(
Object.assign({}, p, {
path: p.path + "#" + h.slug,
header: h
})
);
}
}
}
}
return res;
},
// make suggestions align right when there are not enough items
alignRight() {
const navCount = (this.$site.themeConfig.nav || []).length;
const repo = this.$site.repo ? 1 : 0;
return navCount + repo <= 2;
}
},
methods: {
getPageLocalePath(page) {
for (const localePath in this.$site.locales || {}) {
if (localePath !== "/" && page.path.indexOf(localePath) === 0) {
return localePath;
}
}
return "/";
},
onUp() {
if (this.showSuggestions) {
if (this.focusIndex > 0) {
this.focusIndex--;
} else {
this.focusIndex = this.suggestions.length - 1;
}
}
},
onDown() {
if (this.showSuggestions) {
if (this.focusIndex < this.suggestions.length - 1) {
this.focusIndex++;
} else {
this.focusIndex = 0;
}
}
},
go(i) {
if (!this.showSuggestions) {
return;
}
this.$router.push(this.suggestions[i].path);
this.query = "";
this.focusIndex = 0;
},
focus(i) {
this.focusIndex = i;
},
unfocus() {
this.focusIndex = -1;
}
}
};
</script>

View File

@ -1,70 +1,72 @@
<template>
<div class="sidebar">
<NavLinks class="block md:hidden"/>
<slot name="top"/>
<ul class="sidebar-links" v-if="items.length">
<li v-for="(item, i) in items" :key="i">
<SidebarGroup v-if="item.type === 'group'"
:item="item"
:first="i === 0"
:open="i === openGroupIndex"
:collapsable="item.collapsable"
@toggle="toggleGroup(i)"/>
<SidebarLink v-else :item="item"/>
</li>
</ul>
<slot name="bottom"/>
</div>
<div class="sidebar">
<NavLinks class="block md:hidden" />
<slot name="top" />
<ul class="sidebar-links" v-if="items.length">
<li v-for="(item, i) in items" :key="item.path">
<SidebarGroup
v-if="item.type === 'group'"
:item="item"
:first="i === 0"
:open="i === openGroupIndex"
:collapsable="item.collapsable"
@toggle="toggleGroup(i)"
/>
<SidebarLink v-else :item="item" />
</li>
</ul>
<slot name="bottom" />
</div>
</template>
<script>
import SidebarGroup from './SidebarGroup.vue';
import SidebarLink from './SidebarLink.vue';
import NavLinks from './NavLinks.vue';
import { isActive } from './util';
import SidebarGroup from "./SidebarGroup.vue";
import SidebarLink from "./SidebarLink.vue";
import NavLinks from "./NavLinks.vue";
import { isActive } from "./util";
export default {
components: { SidebarGroup, SidebarLink, NavLinks },
props: ['items'],
data() {
return {
openGroupIndex: 0
};
},
created() {
this.refreshIndex();
},
watch: {
'$route'() {
this.refreshIndex();
}
},
methods: {
refreshIndex() {
const index = resolveOpenGroupIndex(
this.$route,
this.items
);
if (index > - 1) {
this.openGroupIndex = index;
}
},
toggleGroup(index) {
this.openGroupIndex = index === this.openGroupIndex ? - 1 : index;
},
isActive(page) {
return isActive(this.$route, page.path);
}
}
export default {
components: { SidebarGroup, SidebarLink, NavLinks },
props: ["items"],
data() {
return {
openGroupIndex: 0
};
function resolveOpenGroupIndex(route, items) {
for (let i = 0; i < items.length; i ++) {
const item = items[i];
if (item.type === 'group' && item.children.some(c => isActive(route, c.path))) {
return i;
}
}
return - 1;
},
created() {
this.refreshIndex();
},
watch: {
$route() {
this.refreshIndex();
}
},
methods: {
refreshIndex() {
const index = resolveOpenGroupIndex(this.$route, this.items);
if (index > -1) {
this.openGroupIndex = index;
}
},
toggleGroup(index) {
this.openGroupIndex = index === this.openGroupIndex ? -1 : index;
},
isActive(page) {
return isActive(this.$route, page.path);
}
}
};
function resolveOpenGroupIndex(route, items) {
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (
item.type === "group" &&
item.children.some(c => isActive(route, c.path))
) {
return i;
}
}
return -1;
}
</script>

View File

@ -1,28 +1,90 @@
<template>
<div class="sidebar-group" :class="{ first, collapsable }">
<p class="sidebar-heading" :class="{ open }" @click="$emit('toggle')">
<span>{{ item.title }}</span>
<span class="arrow"
v-if="collapsable"
:class="open ? 'down' : 'right'"></span>
</p>
<DropdownTransition>
<ul class="sidebar-group-items" ref="items" v-if="open || !collapsable">
<li v-for="child in item.children">
<SidebarLink :item="child"/>
</li>
</ul>
</DropdownTransition>
</div>
<div class="sidebar-group" :class="{ first, collapsable }">
<p class="sidebar-heading" :class="{ open }" @click="$emit('toggle')">
<span>{{ item.title }}</span>
<span class="arrow" v-if="collapsable" :class="open ? 'down' : 'right'"></span>
<VersionSelect
class="float-right"
v-if="isVersioned"
:versions="item.versions"
v-model="versionSelect"
/>
</p>
<DropdownTransition>
<ul class="sidebar-group-items" ref="items" v-if="open || !collapsable">
<li v-for="child in children">
<SidebarLink :item="child" />
</li>
</ul>
</DropdownTransition>
</div>
</template>
<script>
import SidebarLink from './SidebarLink.vue';
import DropdownTransition from './DropdownTransition.vue';
import SidebarLink from "./SidebarLink.vue";
import DropdownTransition from "./DropdownTransition.vue";
import VersionSelect from "./VersionSelect.vue";
export default {
name: 'SidebarGroup',
props: ['item', 'first', 'open', 'collapsable'],
components: { SidebarLink, DropdownTransition }
export default {
name: "SidebarGroup",
props: ["item", "first", "open", "collapsable"],
components: { SidebarLink, DropdownTransition, VersionSelect },
data: function() {
let isVersioned = this.item.versions.length > 0;
let versionSelect = "";
if (isVersioned) {
versionSelect = this.item.currentVersion || this.item.versions[0].name;
if (this.$router.currentRoute.path.startsWith(this.item.path)) {
const pathVersion = this.$router.currentRoute.path.split("/")[2];
versionSelect = ~this.item.versions
.map(v => v.name)
.indexOf(pathVersion)
? pathVersion
: this.item.currentVersion;
}
}
return {
isVersioned,
versionSelect
};
},
watch: {
versionSelect(newVersion, oldVersion) {
if (
oldVersion !== newVersion &&
this.$router.currentRoute.path.startsWith(this.item.path) &&
this.selectedVersion.children.length > 0
) {
// Try to navigate to the same page in the new version, or default to the first one
let path = this.$router.currentRoute.path;
path = path.substr(path.indexOf(oldVersion) + oldVersion.length);
this.$router.push(
this.selectedVersion.children.find(c => {
return c.path.endsWith(path);
}) || this.selectedVersion.children[0]
);
}
},
$route(to, from) {
if (this.isVersioned && to.path.startsWith(this.item.path)) {
const pathVersion = to.path.split("/")[2];
if (~this.item.versions.map(v => v.name).indexOf(pathVersion)) {
this.versionSelect = pathVersion;
}
}
}
},
computed: {
selectedVersion: function() {
return this.item.versions.find(v => v.name === this.versionSelect);
},
children: function() {
return this.isVersioned
? this.selectedVersion.children
: this.item.children;
}
}
};
</script>

View File

@ -0,0 +1,63 @@
<template>
<div class="version-select custom-select" :tabindex="tabindex" @blur="open = false">
<div class="selected" :class="{open: open}" @click="open = !open">
<VersionSelectItem :version="selected" />
<span class="arrow"></span>
</div>
<div class="items" :class="{hidden: !open}">
<div
class="item"
v-for="version in versions"
:key="version.name"
@click="selected=version; open=false; $emit('input', version.name)"
>
<VersionSelectItem :version="version" />
</div>
</div>
</div>
</template>
<script>
import VersionSelectItem from "./VersionSelectItem.vue";
export default {
name: "VersionSelect",
components: { VersionSelectItem },
props: {
versions: {
type: Array,
required: true
},
tabindex: {
type: Number,
required: false,
default: 0
},
value: {
type: String,
required: false
}
},
data: function() {
return {
selected:
this.versions.find(v => v.name === this.value) ||
(this.versions.length > 0 ? this.versions[0] : null),
open: false
};
},
watch: {
value(newValue, oldValue) {
if (newValue !== oldValue) {
let version = this.versions.find(v => v.name === this.value);
if (version) {
this.selected = version;
}
}
}
},
mounted() {
this.$emit("input", this.selected.name);
}
};
</script>

View File

@ -0,0 +1,32 @@
<template>
<div class="inline-block">
{{ version.name }}
<span class="rounded-full ml-2" :class="classes">{{version.status}}</span>
</div>
</template>
<script>
import VersionSelectItem from "./VersionSelectItem.vue";
export default {
name: "VersionSelectItem",
props: {
version: {
type: Object,
required: true
}
},
computed: {
classes() {
return (
{
deprecated: ["text-orange"],
current: ["text-green-dark"],
stable: ["text-green-dark"],
beta: ["text-blue"]
}[this.version.status] || ["text-grey"]
);
}
}
};
</script>

View File

@ -1,6 +1,6 @@
.content {
code {
@apply .m-0 .text-sm .bg-grey-lighter .rounded .border;
@apply .m-0 .text-sm .border .border-grey-light .bg-grey-lighter .rounded;
padding: .15rem .4rem;
}
@ -28,7 +28,7 @@ div[class*="language-"] {
@apply .relative .bg-grey-darkest .rounded .border .border-black .text-sm .my-4;
.highlight-lines {
@apply .absolute .pin-l .w-full .leading-normal .select-none;
@apply .absolute .left-0 .w-full .leading-normal .select-none;
top: .9rem;
.highlighted {
@ -57,7 +57,7 @@ div[class*="language-"] {
@apply .relative;
&:before {
@apply .absolute .pin-l .pin-t .block .h-full .w-4;
@apply .absolute .left-0 .top-0 .block .h-full .w-4;
content: ' ';
}
}
@ -67,7 +67,7 @@ div[class*="language-"] {
}
.line-numbers-wrapper {
@apply .absolute .pin-t .text-center .w-4;
@apply .absolute .top-0 .text-center .w-4;
br {
@apply .select-none;
@ -78,7 +78,7 @@ div[class*="language-"] {
}
}
&::after {
@apply .absolute .pin-t .pin-l .h-full .w-4;
@apply .absolute .top-0 .left-0 .h-full .w-4;
content: '';
}
}

View File

@ -1,10 +1,10 @@
@font-face {
font-family: 'et-line';
src:url('../fonts/et-line/et-line.eot');
src:url('../fonts/et-line/et-line.eot?#iefix') format('embedded-opentype'),
url('../fonts/et-line/et-line.woff') format('woff'),
url('../fonts/et-line/et-line.ttf') format('truetype'),
url('../fonts/et-line/et-line.svg#et-line') format('svg');
src:url('./fonts/et-line/et-line.eot');
src:url('./fonts/et-line/et-line.eot?#iefix') format('embedded-opentype'),
url('./fonts/et-line/et-line.woff') format('woff'),
url('./fonts/et-line/et-line.ttf') format('truetype'),
url('./fonts/et-line/et-line.svg#et-line') format('svg');
font-weight: normal;
font-style: normal;
}

View File

@ -1,4 +1,4 @@
@import "tailwindcss/preflight";
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "./layout.css";

View File

@ -7,7 +7,7 @@
@apply .px-6;
.logo-container {
@apply .flex-no-shrink;
@apply .flex-shrink-0;
width: 18.5rem; /* sidebar is 20rem + 1.5rem padding on each side for nav */
}
@ -50,7 +50,7 @@
input {
transition: all 200ms ease-in;
@apply .text-grey-lighter .w-1/2 .outline-none .px-4 .py-2 .rounded;
@apply .text-grey-lighter .w-1/2 .outline-none .px-4 .py-2 .rounded .leading-tight;
background: rgba(0, 0, 0, 0.2);
border: 1px solid rgba(0, 0, 0, 0.3);

View File

@ -5,13 +5,13 @@ $arrow-bg: #000;
@apply .hidden;
}
@apply .fixed .pin-l .pin-b .bg-white .overflow-auto .border-r .border-grey-lighter .py-8;
@apply .fixed .left-0 .bottom-0 .bg-white .overflow-auto .border-r .border-grey-lighter .py-8;
top: 56px;
width: 20rem;
font-size: 15px;
ul {
@apply .list-reset .m-0;
@apply .m-0 .p-0;
}
a {
@ -90,6 +90,56 @@ $arrow-bg: #000;
&.open .arrow {
top: -0.18em;
}
.version-select {
@apply .relative .inline-block .text-sm;
&:focus {
@apply .outline-none;
}
.selected {
@apply .select-none .border .border-grey-lighter .cursor-pointer .px-4;
border-radius: 1rem;
&:hover, &.open {
@apply .bg-grey-lighter .border-grey-lighter;
}
.arrow {
@apply .inline-block .relative;
top: -0.16em;
left: .5em;
width: 0;
height: 0;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 6px solid #b8c2cc;
}
}
.items {
@apply .absolute .right-0 .bg-white .shadow .p-1 .mt-1;
border-radius: 1rem;
z-index: 100;
.item {
@apply .select-none .rounded-full .cursor-pointer .px-2 .border .border-white;
white-space: nowrap;
margin-top: .125rem;
margin-bottom: .125rem;
&:hover, &:focus {
@apply .bg-grey-lighter;
}
&:last-child {
@apply .mb-0;
}
}
}
}
}
.sidebar-group-items {
@ -125,7 +175,7 @@ $arrow-bg: #000;
}
.sidebar-mask {
@apply .fixed .pin-t .pin-l .h-screen .w-screen .hidden;
@apply .fixed .top-0 .left-0 .h-screen .w-screen .hidden;
}
.sidebar-open > .sidebar {

View File

@ -118,7 +118,7 @@
@charset 'UTF-8';
/* Slider */
.slick-loading .slick-list {
background: #fff url('../../public/frontpage/loading.svg') center center no-repeat;
background: #fff url('../public/frontpage/loading.svg') center center no-repeat;
}
/* Icons */
@ -127,8 +127,8 @@
font-weight: normal;
font-style: normal;
src: url('../fonts/slick/slick.eot');
src: url('../fonts/slick/slick.eot?#iefix') format('embedded-opentype'), url('../fonts/slick/slick.woff') format('woff'), url('../fonts/slick/slick.ttf') format('truetype'), url('../fonts/slick/slick.svg#slick') format('svg');
src: url('./fonts/slick/slick.eot');
src: url('./fonts/slick/slick.eot?#iefix') format('embedded-opentype'), url('./fonts/slick/slick.woff') format('woff'), url('./fonts/slick/slick.ttf') format('truetype'), url('./fonts/slick/slick.svg#slick') format('svg');
}
/* Arrows */

View File

@ -14,12 +14,20 @@ a {
}
}
kbd {
@apply .border .border-grey-lighter .bg-grey-lightest;
}
.content {
ul, ol {
@apply .ml-6 .pl-8 .my-2;
}
ul {
list-style-type: disc;
padding-left: theme('padding.4');
}
ul, ol {
@apply .pl-8 .my-2;
ol {
list-style-type: decimal;
padding-left: theme('padding.4');
}
}
strong {
@ -65,15 +73,12 @@ h1 {
}
h2 {
@apply .pb-2 .border-b;
@apply .text-2xl .pb-2 .border-b .border-grey-light;
}
p {
@apply .my-4;
}
code, kbd, .line-number {
@apply font-mono;
line-height: 1.7;
}
p, ul, ol {
@ -97,7 +102,7 @@ table {
}
th, td {
@apply .border .py-2 .px-4;
@apply .border .py-2 .px-4 .border-grey-light;
}
td {

View File

@ -3,32 +3,32 @@ export const extRE = /\.(md|html)$/
export const endingSlashRE = /\/$/
export const outboundRE = /^(https?:|mailto:|tel:)/
export function normalize (path) {
export function normalize(path) {
return decodeURI(path)
.replace(hashRE, '')
.replace(extRE, '')
}
export function getHash (path) {
export function getHash(path) {
const match = path.match(hashRE)
if (match) {
return match[0]
}
}
export function isExternal (path) {
export function isExternal(path) {
return outboundRE.test(path)
}
export function isMailto (path) {
export function isMailto(path) {
return /^mailto:/.test(path)
}
export function isTel (path) {
export function isTel(path) {
return /^tel:/.test(path)
}
export function ensureExt (path) {
export function ensureExt(path) {
if (isExternal(path)) {
return path
}
@ -42,7 +42,7 @@ export function ensureExt (path) {
return normalized + '.html' + hash
}
export function isActive (route, path) {
export function isActive(route, path) {
const routeHash = route.hash
const linkHash = getHash(path)
if (linkHash && routeHash !== linkHash) {
@ -53,7 +53,7 @@ export function isActive (route, path) {
return routePath === pagePath
}
export function resolvePage (pages, rawPath, base) {
export function resolvePage(pages, rawPath, base) {
if (base) {
rawPath = resolvePath(rawPath, base)
}
@ -70,7 +70,7 @@ export function resolvePage (pages, rawPath, base) {
return {}
}
function resolvePath (relative, base, append) {
function resolvePath(relative, base, append) {
const firstChar = relative.charAt(0)
if (firstChar === '/') {
return relative
@ -108,7 +108,7 @@ function resolvePath (relative, base, append) {
return stack.join('/')
}
export function resolveSidebarItems (page, route, site, localePath) {
export function resolveSidebarItems(page, route, site, localePath) {
const { pages, themeConfig } = site
const localeConfig = localePath && themeConfig.locales
@ -131,7 +131,7 @@ export function resolveSidebarItems (page, route, site, localePath) {
}
}
function resolveHeaders (page) {
function resolveHeaders(page) {
const headers = groupHeaders(page.headers || [])
return [{
type: 'group',
@ -147,7 +147,7 @@ function resolveHeaders (page) {
}]
}
export function groupHeaders (headers) {
export function groupHeaders(headers) {
// group h3s under h2
headers = headers.map(h => Object.assign({}, h))
let lastH2
@ -161,13 +161,13 @@ export function groupHeaders (headers) {
return headers.filter(h => h.level === 2)
}
export function resolveNavLinkItem (linkItem) {
export function resolveNavLinkItem(linkItem) {
return Object.assign(linkItem, {
type: linkItem.items && linkItem.items.length ? 'links' : 'link'
})
}
export function resolveMatchingConfig (route, config) {
export function resolveMatchingConfig(route, config) {
if (Array.isArray(config)) {
return {
base: '/',
@ -185,13 +185,13 @@ export function resolveMatchingConfig (route, config) {
return {}
}
function ensureEndingSlash (path) {
function ensureEndingSlash(path) {
return /(\.html|\/)$/.test(path)
? path
: path + '/'
}
function resolveItem (item, pages, base, isNested) {
function resolveItem(item, pages, base, isNested) {
if (typeof item === 'string') {
return resolvePage(pages, item, base)
} else if (Array.isArray(item)) {
@ -206,11 +206,17 @@ function resolveItem (item, pages, base, isNested) {
)
}
const children = item.children || []
const versions = item.versions || []
return {
type: 'group',
title: item.title,
...item,
children: children.map(child => resolveItem(child, pages, base, true)),
collapsable: item.collapsable !== false
collapsable: item.collapsable !== false,
versions: versions.map(version => ({
...version,
status: version.name === item.currentVersion ? "current" : version.status,
children: version.children.map(child => resolveItem(item.path + version.name + child, pages, base, true))
})),
}
}
}

0
404.md Normal file
View File

View File

@ -18,7 +18,7 @@ Give theme name:
> (Press Enter)
Where will assets be located? []:
> /themes/(MyThemeNameHere) (Example: /themes/MyThemeNameHere)
> themes/(MyThemeNameHere) (Example: themes/MyThemeNameHere)
Extends an other theme? (yes/no) [no]:
> (Press Enter)

View File

@ -148,3 +148,9 @@ Starting with `v0.6` of the Daemon, the following previously _dropped_ capabilit
'setfcap',
]
```
## Enabling Cloudflare
Enabling Cloudflare on the daemon isn't particularly useful since users do not connect directly to the daemon port, and users need an unproxied hostname to access any servers on the node. As a result it's not possible to conceal the IP address of your node machine, but some people want to enable it regardless.
Cloudflare only proxies the default daemon port (8080) when using HTTP. In order to get the daemon to work with Cloudflare when HTTPS is enabled you must change the daemon port to one that Cloudflare will proxy such as 8443. Since Cloudflare only proxies HTTP/HTTPS traffic for non-enterprise plans you cannot proxy the SFTP port.

View File

@ -5,17 +5,12 @@
## Supported Systems
| Operating System | Version | Supported | Notes |
| ---------------- | ------- | :-------: | ----- |
| **Ubuntu** | 14.04 | :warning: | Approaching EOL, not recommended for new installations. |
| | 16.04 | :white_check_mark: | |
| | 18.04 | :white_check_mark: | |
| **CentOS** | 6 | :no_entry_sign: | Does not support all of the required packages. |
| | 7 | :white_check_mark: | |
| **Debian** | 8 | :warning: | Requires [kernel modifications](debian_8_docker.md) to run Docker. |
| | 9 | :white_check_mark: | |
| **Alpine Linux** | 3.4+ | :warning: | Not officially supported, but reportedly works. |
| **RHEL** | 7 | :warning: | Not officially supported, should work. |
| **Fedora** | 28 | :warning: | Not officially supported, should work. |
| | 29 | :warning: | Not officially supported, should work. |
| **Ubuntu** | 18.04 | :white_check_mark: | Documentation written assuming Ubuntu 18.04 as the base OS. |
| | 20.04 | :white_check_mark: |
| **CentOS** | 7 | :warning: | Extra repos are required |
| | 8 | :white_check_mark: | |
| **Debian** | 9 | :white_check_mark: | |
| | 10 | :white_check_mark: | |
## System Requirements
In order to run the Daemon you will need a system capable of running Docker containers. Most VPS and almost all
@ -148,7 +143,7 @@ Once you have done that there will be a tab called Configuration when you view t
Simply copy and paste the code block and paste it into a file called `core.json` in `/srv/daemon/config` and save it.
You may also use the Auto-Deployment feature rather than manually creating the files.
![](./../.vuepress/public/daemon_configuration_example.png)
![](./../../.vuepress/public/daemon_configuration_example.png)
## Starting the Daemon
To start your daemon simply move into the daemon directory and run the command below which will start the daemon in
@ -192,18 +187,3 @@ Then, run the commands below to reload systemd and start the daemon.
``` bash
systemctl enable --now wings
```
### Daemonizing (using Forever)
Forever allows us to run the daemon as a pseudo-daemonized application. We can exit our terminal session without
killing the process, and we don't have to run it in a screen. Inside the daemon directory, run the commands below which
will install forever and then start the process in the background.
You should use this only if your system does not support systemd.
``` bash
npm install -g forever
forever start src/index.js
# To stop the daemon use:
forever stop src/index.js
```

View File

@ -1,19 +1,21 @@
{
"dependencies": {
"@vuepress/plugin-google-analytics": "^1.0.0-rc.1",
"jquery": "^3.3.1",
"slick-carousel": "^1.8.1",
"vuepress": "^0.14.8"
"vuepress": "^1.4.0",
"vuepress-plugin-container": "^2.1.3"
},
"scripts": {
"build": "./node_modules/vuepress/bin/vuepress.js build",
"watch": "./node_modules/vuepress/bin/vuepress.js dev"
"build": "vuepress build",
"watch": "vuepress dev"
},
"devDependencies": {
"autoprefixer": "^9.0.1",
"cssnano": "^4.0.3",
"lodash": "^4.17.13",
"postcss-import": "^11.1.0",
"precss": "^3.1.2",
"tailwindcss": "^0.6.4"
"postcss-import": "^12.0.0",
"precss": "^4.0.0",
"tailwindcss": "^1.0.0"
}
}

View File

@ -20,14 +20,11 @@ this software on an OpenVZ based system you will &mdash; most likely &mdash; not
| Operating System | Version | Supported | Notes |
| ---------------- | ------- | :-------: | ----- |
| **Ubuntu** | 14.04 | :warning: | Documentation assumes changes to `systemd` introduced in `16.04` |
| | 16.04 | :warning: | Ubuntu 16.04 is nearing end of life. |
| | 18.04 | :white_check_mark: | Documentation written assuming Ubuntu 18.04 as the base OS. |
| **CentOS** | 6 | :no_entry_sign: | Does not support all of the required packages. |
| | 7 | :white_check_mark: | Extra repos are required. |
| **Ubuntu** | 18.04 | :white_check_mark: | Documentation written assuming Ubuntu 18.04 as the base OS. |
| | 20.04 | :white_check_mark: | |
| **CentOS** | 7 | :white_check_mark: | Extra repos are required. |
| | 8 | :white_check_mark: | All required packages are part of the base repos. |
| **Debian** | 8 | :warning: | Debian 8 may need modifications to work with the latest docker and other requirements for the panel/daemon |
| | 9 | :white_check_mark: | Extra repos are required. |
| **Debian** | 9 | :white_check_mark: | Extra repos are required. |
| | 10 | :white_check_mark: | All required packages are part of the base repos. |
## Dependencies

View File

@ -2,6 +2,11 @@
[[toc]]
::: danger Not for Production Use
**This is a beta version that should not be used in a production environment.**
Features haven't been fully tested and might be incomplete or broken. There is no supported way to upgrade. You should test this version with a separate installation.
:::
Pterodactyl Panel is designed to run on your own web server. You will need to have root access to your server in order to run and use this panel.
You are expected to understand how to read documentation to use this Panel. We have spent many hours detailing how to install or upgrade our
@ -20,13 +25,11 @@ this software on an OpenVZ based system you will &mdash; most likely &mdash; not
| Operating System | Version | Supported | Notes |
| ---------------- | ------- | :-------: | ----- |
| **Ubuntu** | 16.04 | :warning: | Ubuntu 16.04 is nearing end of life. |
| | 18.04 | :white_check_mark: | Documentation written assuming Ubuntu 18.04 as the base OS. |
| **CentOS** | 6 | :no_entry_sign: | Does not support all of the required packages. |
| | 7 | :white_check_mark: | Extra repos are required. |
| **Ubuntu** | 18.04 | :white_check_mark: | Documentation written assuming Ubuntu 18.04 as the base OS. |
| | 20.04 | :white_check_mark: | |
| **CentOS** | 7 | :white_check_mark: | Extra repos are required. |
| | 8 | :white_check_mark: | All required packages are part of the base repos. |
| **Debian** | 8 | :warning: | Debian 8 may need modifications to work with the latest docker and other requirements for the panel/daemon |
| | 9 | :white_check_mark: | Extra repos are required. |
| **Debian** | 9 | :white_check_mark: | Extra repos are required. |
| | 10 | :white_check_mark: | All required packages are part of the base repos. |
## Dependencies

View File

@ -17,7 +17,7 @@ members can be found in our Discord channel and are distinguished with a yellow
## License
``` text
Copyright (c) 2015 - 2019 Dane Everitt <dane@daneeveritt.com>.
Copyright (c) 2015 - 2020 Dane Everitt <dane@daneeveritt.com>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,9 +1,10 @@
# Community Standards
<!--
Sorry, but this file is off limits to additions or deletions that are not the result of fixing
grammar or spelling mistakes.
-->
# Community Standards
Pterodactyl prides itself on providing a warm and welcoming community for all of our members. However, due to the
sheer size of our community, we have a few rules that we expect all individuals to follow at all times.

View File

@ -24,7 +24,6 @@ In addition to our standard nest of supported games, our community is constantly
and there are plenty more games available provided by the community. Some of these games include:
* Factorio
* Terraria
* San Andreas: MP
* Pocketmine MP
* Squad

View File

@ -123,6 +123,36 @@ let colors = {
'pink-lightest': '#ffebef',
}
module.exports = {
prefix: '',
important: false,
separator: ':',
theme: {
colors,
screens: {
'sm': '576px',
'md': '768px',
'lg': '992px',
'xl': '1200px',
'xsx': { 'max': '575px' },
'smx': { 'max': '767px' },
'mdx': { 'max': '991px' },
'lgx': { 'max': '1999px' },
},
},
variants: {
appearance: ['responsive'],
// ...
zIndex: ['responsive'],
},
plugins: [
// ...
],
}
return
module.exports = {
/*
@ -166,10 +196,10 @@ module.exports = {
'lg': '992px',
'xl': '1200px',
'xsx': {'max': '575px'},
'smx': {'max': '767px'},
'mdx': {'max': '991px'},
'lgx': {'max': '1999px'},
'xsx': { 'max': '575px' },
'smx': { 'max': '767px' },
'mdx': { 'max': '991px' },
'lgx': { 'max': '1999px' },
},

View File

@ -14,18 +14,12 @@ This software _requires Pterodactyl 1.0_ in order to run.
## Supported Systems
| Operating System | Version | Supported | Notes |
| ---------------- | ------- | :-------: | ----- |
| **Ubuntu** | 14.04 | :no_entry_sign: | Does not support `systemd`. |
| | 16.04 | :white_check_mark: | |
| | 18.04 | :white_check_mark: | |
| **CentOS** | 6 | :no_entry_sign: | Does not support all of the required packages. |
| | 7 | :white_check_mark: | |
| **Debian** | 8 | :warning: | Requires [kernel modifications](/daemon/debian_8_docker.md) to run Docker. |
| | 9 | :white_check_mark: | |
| **Ubuntu** | 18.04 | :white_check_mark: | Documentation written assuming Ubuntu 18.04 as the base OS. |
| | 20.04 | :white_check_mark: | |
| **CentOS** | 7 | :white_check_mark: | |
| | 8 | :white_check_mark: | |
| **Debian** | 9 | :white_check_mark: | |
| | 10 | :white_check_mark: | |
| **Alpine Linux** | 3.4+ | :warning: | Not officially supported, but reportedly works. |
| **RHEL** | 7 | :warning: | Not officially supported, should work. |
| **Fedora** | 28 | :warning: | Not officially supported, should work. |
| | 29 | :warning: | Not officially supported, should work. |
## System Requirements
In order to run the Daemon you will need a system capable of running Docker containers. Most VPS and almost all
@ -124,7 +118,7 @@ Once you have done that there will be a tab called Configuration when you view t
Simply copy and paste the code block and paste it into a file called `config.yml` in `/srv/wings` and save it.
![](./../.vuepress/public/wings_configuration_example.png)
![](./../../.vuepress/public/wings_configuration_example.png)
### Starting Wings
To start your daemon simply move into the daemon directory and run the command below which will start the daemon in

8964
yarn.lock

File diff suppressed because it is too large Load Diff