Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Plugin md Files #257

Merged
merged 13 commits into from
Feb 15, 2024
Merged
9 changes: 9 additions & 0 deletions .vitepress/config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {defineConfig} from '@lando/vitepress-theme-default-plus/config';

const hat = '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"><path stroke-linecap="round" stroke-linejoin="round" d="M4.26 10.147a60.438 60.438 0 0 0-.491 6.347A48.62 48.62 0 0 1 12 20.904a48.62 48.62 0 0 1 8.232-4.41 60.46 60.46 0 0 0-.491-6.347m-15.482 0a50.636 50.636 0 0 0-2.658-.813A59.906 59.906 0 0 1 12 3.493a59.903 59.903 0 0 1 10.399 5.84c-.896.248-1.783.52-2.658.814m-15.482 0A50.717 50.717 0 0 1 12 13.489a50.702 50.702 0 0 1 7.74-3.342M6.75 15a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm0 0v-3.675A55.378 55.378 0 0 1 12 8.443m-7.007 11.55A5.981 5.981 0 0 0 6.75 15.75v-1.5" /></svg>';
const puzzle = '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"><path stroke-linecap="round" stroke-linejoin="round" d="M14.25 6.087c0-.355.186-.676.401-.959.221-.29.349-.634.349-1.003 0-1.036-1.007-1.875-2.25-1.875s-2.25.84-2.25 1.875c0 .369.128.713.349 1.003.215.283.401.604.401.959v0a.64.64 0 0 1-.657.643 48.39 48.39 0 0 1-4.163-.3c.186 1.613.293 3.25.315 4.907a.656.656 0 0 1-.658.663v0c-.355 0-.676-.186-.959-.401a1.647 1.647 0 0 0-1.003-.349c-1.036 0-1.875 1.007-1.875 2.25s.84 2.25 1.875 2.25c.369 0 .713-.128 1.003-.349.283-.215.604-.401.959-.401v0c.31 0 .555.26.532.57a48.039 48.039 0 0 1-.642 5.056c1.518.19 3.058.309 4.616.354a.64.64 0 0 0 .657-.643v0c0-.355-.186-.676-.401-.959a1.647 1.647 0 0 1-.349-1.003c0-1.035 1.008-1.875 2.25-1.875 1.243 0 2.25.84 2.25 1.875 0 .369-.128.713-.349 1.003-.215.283-.4.604-.4.959v0c0 .333.277.599.61.58a48.1 48.1 0 0 0 5.427-.63 48.05 48.05 0 0 0 .582-4.717.532.532 0 0 0-.533-.57v0c-.355 0-.676.186-.959.401-.29.221-.634.349-1.003.349-1.035 0-1.875-1.007-1.875-2.25s.84-2.25 1.875-2.25c.37 0 .713.128 1.003.349.283.215.604.401.96.401v0a.656.656 0 0 0 .658-.663 48.422 48.422 0 0 0-.37-5.36c-1.886.342-3.81.574-5.766.689a.578.578 0 0 1-.61-.58v0Z" /></svg>';

export default defineConfig({
title: 'Lando',
Expand Down Expand Up @@ -32,6 +33,14 @@ export default defineConfig({
iconLink: '/lando-101',
patterns: ['lando-101/**/*.md'],
},
plugins: {
frontmatter: {
collection: 'plugins',
},
icon: puzzle,
iconLink: '/plugins',
patterns: ['plugins/**/*.md'],
},
post: {
frontmatter: {
collection: 'post',
Expand Down
267 changes: 267 additions & 0 deletions .vitepress/theme/VPLPluginItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
<template>
<VPLLink
class="plugin"
:href="link"
:no-icon="true"
:tag="link ? 'a' : 'div'"
>
<article
v-if="type === 'article'"
:class="`box ${type}`"
>
ARTICLE
</article>

<article
v-else-if="type === 'icon'"
:class="`box ${type}`"
>
<div
v-if="typeof icon === 'object' && icon.wrap"
class="image"
>
<VPImage
:image="icon"
:alt="icon.alt"
:height="icon.height || 48"
:width="icon.width || 48"
/>
</div>
<VPImage
v-else-if="typeof icon === 'object'"
:image="icon"
:alt="icon.alt"
:height="icon.height || 48"
:width="icon.width || 48"
/>
<div
v-else-if="icon"
class="image"
v-html="icon"
/>
<h2
class="title"
v-html="title"
/>
</article>

<article
v-else
:class="`box card ${type}`"
>
<div
v-if="typeof icon === 'object' && icon.wrap"
class="image"
>
<VPImage
:image="icon"
:alt="icon.alt"
:height="icon.height || 48"
:width="icon.width || 48"
/>
</div>
<VPImage
v-else-if="typeof icon === 'object'"
:image="icon"
:alt="icon.alt"
:height="icon.height || 48"
:width="icon.width || 48"
/>
<div
v-else-if="icon"
class="image"
v-html="icon"
/>
<h2
class="title"
v-html="title"
/>
<p
v-if="details"
class="details"
v-html="details"
/>

<div
class="footer"
>
<div class="link-text">
<p
v-if="linkText"
class="link-text-value"
>
{{ linkText }} <VPIconArrowRight class="link-text-icon" />
</p>
</div>

<div
v-if="maintainers"
class="maintainers"
>
<div class="maintainers-flex">
<VPLTeamMembersItem
v-for="maintainer in maintainers"
:key="maintainer.key"
:member="maintainer"
size="icon"
/>
</div>
</div>
</div>
</article>
</VPLLink>
</template>

<script setup>
import {computed} from 'vue';
import {useData} from 'vitepress';
import {VPImage} from 'vitepress/theme';
import {VPLLink, VPLTeamMembersItem} from '@lando/vitepress-theme-default-plus';
import VPIconArrowRight from 'vitepress/dist/client/theme-default/components/icons/VPIconArrowRight.vue';

const {plugin, type} = defineProps({
plugin: {
type: Object,
required: true,
},
type: {
type: String,
default: 'card',
},
});

const {theme} = useData();

const details = computed(() => plugin.summary ?? plugin.description);
const link = computed(() => plugin.link ?? plugin.url);
const linkText = computed(() => plugin.linkText ?? '');
const maintainers = computed(() => plugin.maintainers ?? false);

const title = computed(() => {
if (typeof plugin.title === 'string' && plugin.title.toUpperCase().endsWith('PLUGIN')) {
return plugin.title.slice(0, -7);
}
return plugin.title;
});

const icon = computed(() => {
// prefer a plugin image
if (plugin.image) {
return {
alt: plugin.title,
src: plugin.image,
wrap: true,
};
}
// and then an icon if we have that
if (plugin.icon) return plugin.icon;
// and then the collection icon
if (theme.value?.collections?.plugins?.icon) return theme.value.collections.plugins.icon;
// and finally this fucking thing
return '🧩';
});

</script>

<style lang="scss" scoped>
.plugin {
display: block;
border: 1px solid var(--vp-c-bg-soft);
border-radius: 12px;
height: 100%;
background-color: var(--vp-c-bg-soft);
transition: border-color 0.25s, background-color 0.25s;
}

.plugin.link:hover {
border-color: var(--vp-c-brand-1);
}

.box {
display: flex;
flex-direction: column;
padding: 24px;
height: 100%;
&.icon {
text-align: center;
gap: 12px;
.image {
margin: auto;
}
}
}

.box > :deep(.VPImage) {
margin-bottom: 20px;
}

.image {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
border-radius: 6px;
background-color: var(--vp-c-default-soft);
width: 48px;
height: 48px;
font-size: 24px;
transition: background-color 0.25s;
}

.maintainers {
display: flex;
justify-content: flex-end;
margin-right: -10px;
.VPTeamMembersItem.icon {
overflow: visible;
margin-left: -14px;
}
}
.maintainers-flex {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
}

.title {
line-height: 24px;
font-size: 16px;
font-weight: 600;
}

.details {
flex-grow: 1;
padding-top: 8px;
line-height: 24px;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-text-2);
}

.footer {
margin-top: 12px;
display: flex;
align-items: center;
justify-content: space-between;
}

.link-text {
padding-top: 0px;
}

.link-text-value {
display: flex;
align-items: center;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-brand-1);
}

.link-text-icon {
display: inline-block;
margin-left: 6px;
width: 14px;
height: 14px;
fill: currentColor;
}
</style>
Loading
Loading