Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export default defineAppConfig({
prose: {
codePreview: {
slots: {
preview: 'flex-col [&>*]:w-full [&_a]:w-fit',
preview: 'flex-col *:w-full [&_a]:w-fit',
},
},
codeIcon: {
Expand Down
42 changes: 42 additions & 0 deletions docs/app/components/Browser.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<script setup lang="ts">
defineProps<{
src: string
}>()
</script>

<template>
<div class="border border-muted rounded-lg overflow-hidden my-6 not-prose">
<div class="flex items-center gap-2 px-3 py-2 bg-elevated border-b border-muted">
<div class="flex gap-1.5 mr-1">
<span class="size-3 rounded-full bg-red-400/80" />
<span class="size-3 rounded-full bg-yellow-400/80" />
<span class="size-3 rounded-full bg-green-400/80" />
</div>

<div class="flex-1 flex items-center gap-1.5 bg-default rounded-md px-2 py-1.5 text-xs text-muted font-mono truncate border border-muted">
<UIcon
name="i-lucide-lock"
class="size-3.5 shrink-0 text-green-500 dark:text-green-400"
/>
<span class="truncate select-all">{{ src }}</span>
</div>

<UButton
icon="i-lucide-external-link"
:to="src"
target="_blank"
size="xs"
variant="ghost"
color="neutral"
aria-label="Open in new tab"
/>
</div>

<iframe
:src="src"
class="w-full border-0 bg-white aspect-9/16 sm:aspect-video"
allow="clipboard-read; clipboard-write"
loading="lazy"
/>
</div>
</template>
155 changes: 155 additions & 0 deletions docs/app/components/CodeExplorer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<script setup lang="ts">
import type { ComarkTree } from 'comark'
import { ComarkRenderer } from '@comark/vue'
import CodeIcon from '@nuxt/ui/components/prose/CodeIcon.vue'

interface CodeExplorerTreeItem {
filename: string
path: string
children?: CodeExplorerTreeItem[]
defaultExpanded?: boolean
}

interface CodeExplorerData {
tree: CodeExplorerTreeItem[]
files: Record<string, ComarkTree>
}

const props = withDefaults(defineProps<{
org: string
repo: string
path: string
branch?: string
defaultValue?: string
}>(), {
branch: 'main',
})

const repoSegment = computed(() => {
if (props.branch === 'main') return props.repo
return `${props.repo}@${props.branch.replaceAll('/', '~')}`
})

const apiUrl = computed(() => `/api/code-explorer/${props.org}/${repoSegment.value}/${props.path}.json`)

prerenderRoutes([apiUrl.value])
const nuxtApp = useNuxtApp()
const { data } = await useFetch<CodeExplorerData>(apiUrl, {
getCachedData: key => nuxtApp.payload.data[key],
})

const selected = ref(props.defaultValue ? findFile(props.defaultValue, data.value?.tree) : findFirstFile(data.value?.tree))
const selectedFile = computed(() => selected.value ? data.value?.files[selected.value.path] : undefined)

expandDefaultSelected(data.value?.tree)

function findFirstFile(items: CodeExplorerTreeItem[] = []): CodeExplorerTreeItem | undefined {
for (const item of items) {
if (!item.children) return item
const found = findFirstFile(item.children)
if (found) return found
}
}

function findFile(path: string, items: CodeExplorerTreeItem[] = []): CodeExplorerTreeItem | undefined {
for (const item of items) {
if (item.path === path) return item
if (item.children) {
const found = findFile(path, item.children)
if (found) return found
}
}
}

function expandDefaultSelected(items: CodeExplorerTreeItem[] = []) {
for (const item of items) {
if (item.children && selected.value?.path.startsWith(item.path + '/')) {
item.defaultExpanded = true
expandDefaultSelected(item.children)
}
}
}

function onSelect(e: Event, item: CodeExplorerTreeItem) {
if (item?.children || item.path === selected.value?.path) {
e.preventDefault()
}
}
</script>

<template>
<div
v-if="data"
class="relative border border-muted rounded-lg overflow-hidden not-prose"
>
<div class="grid lg:grid-cols-3 lg:h-[450px]">
<div class="p-2 border-b lg:border-b-0 lg:border-r border-muted overflow-y-auto">
<UTree
v-model="selected"
:items="data.tree"
color="neutral"
:get-key="(item) => item.path"
label-key="filename"
:ui="{ linkLeadingIcon: 'size-4' }"
@select="onSelect"
>
<template #item-leading="{ item, ui }">
<CodeIcon
v-if="!item.children?.length"
:filename="item.filename"
:class="ui.linkLeadingIcon({ class: 'size-4' })"
/>
</template>
</UTree>
</div>

<div class="lg:col-span-2 overflow-auto flex flex-col">
<div
v-if="selected"
class="flex items-center gap-1.5 border-b border-muted bg-muted/50 px-4 py-2"
>
<CodeIcon :filename="selected.filename" />
<span class="font-mono text-xs text-muted truncate">{{ selected.filename }}</span>
</div>

<div
v-if="selectedFile"
class="code-explorer-content flex-1 flex-col"
>
<UTheme :ui="{ prose: { pre: { root: 'my-0 h-full' } } }">
<ComarkRenderer
:tree="selectedFile"
class="h-full"
/>
</UTheme>
</div>

<div
v-else
class="flex items-center justify-center h-full p-8 text-sm text-muted"
>
Select a file to view its contents
</div>
</div>
</div>
</div>
</template>

<style scoped>
.code-explorer-content :deep(pre) {
margin: 0;
border: 0;
border-radius: 0;
height: 100%;
}

.code-explorer-content :deep(.shiki span.line) {
display: inline-block;
}
</style>

<style>
.dark .shiki span {
color: var(--shiki-dark) !important;
}
</style>
2 changes: 1 addition & 1 deletion docs/app/components/landing/LandingCode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ defineProps<{
const activeTab = ref<'vue' | 'react'>('vue')

const vueCode = `<script setup lang="ts">
import { Comark } from 'comark/vue'
import { Comark } from '@comark/vue'
import Alert from './components/Alert.vue'

const components = { Alert }
Expand Down
2 changes: 1 addition & 1 deletion docs/app/components/landing/LandingFeatureFrameworks.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
const activeTab = ref<'vue' | 'react'>('vue')

const vueCode = `<script setup lang="ts">
import { Comark } from 'comark/vue'
import { Comark } from '@comark/vue'
import Alert from './components/Alert.vue'

const md = \`
Expand Down Expand Up @@ -107,12 +107,12 @@
<div
v-show="activeTab === 'vue'"
class="text-sm/6"
v-html="highlighted?.vue"

Check warning on line 110 in docs/app/components/landing/LandingFeatureFrameworks.vue

View workflow job for this annotation

GitHub Actions / test

'v-html' directive can lead to XSS attack
/>
<div
v-show="activeTab === 'react'"
class="text-sm/6"
v-html="highlighted?.react"

Check warning on line 115 in docs/app/components/landing/LandingFeatureFrameworks.vue

View workflow job for this annotation

GitHub Actions / test

'v-html' directive can lead to XSS attack
/>
</div>
</div>
Expand Down
24 changes: 17 additions & 7 deletions docs/app/pages/examples/[...slug].vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,22 +79,32 @@ defineOgImageComponent('Docs', {
</template>
<template #links>
<UButton
icon="i-simple-icons-stackblitz"
label="Open in Playground"
icon="i-simple-icons-github"
label="Source"
color="neutral"
variant="soft"
size="sm"
:to="`https://stackblitz.com/fork/github/${appConfig.docs?.github}/tree/${appConfig.docs?.branch || 'main'}/examples/${exampleName}`"
:to="`https://github.com/${appConfig.docs?.github}/tree/${appConfig.docs?.branch || 'main'}/examples/${exampleName}`"
target="_blank"
/>

<UButton
icon="i-simple-icons-github"
label="Source"
v-if="page.demo"
trailing-icon="i-lucide-arrow-up-right"
label="Open demo"
color="neutral"
variant="soft"
size="sm"
:to="`https://github.com/${appConfig.docs?.github}/tree/${appConfig.docs?.branch || 'main'}/examples/${exampleName}`"
:to="page.demo"
target="_blank"
/>
<UButton
v-else
icon="i-simple-icons-stackblitz"
label="Open in StackBlitz"
color="neutral"
variant="soft"
size="sm"
:to="`https://stackblitz.com/fork/github/${appConfig.docs?.github}/tree/${appConfig.docs?.branch || 'main'}/examples/${exampleName}`"
target="_blank"
/>
</template>
Expand Down
1 change: 1 addition & 0 deletions docs/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default defineContentConfig({
schema: z.object({
category: z.string().optional(),
icon: z.string().optional(),
demo: z.string().optional(),
}),
}),
},
Expand Down
30 changes: 17 additions & 13 deletions docs/content/4.plugins/1.core/02.highlight.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,16 @@ import highlight from 'comark/plugins/highlight'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'

const content = `
const plugins = [
highlight({
themes: {
light: githubLight,
dark: githubDark
}
})
]

const md = `
\`\`\`javascript
const greeting = "Hello World"
console.log(greeting)
Expand All @@ -120,20 +129,15 @@ console.log(greeting)

<template>
<Suspense>
<Comark
:plugins="[
highlight({
themes: {
light: githubLight,
dark: githubDark
}
})
]"
>
{{ content }}
</Comark>
<Comark :plugins="plugins" :markdown="md" />
</Suspense>
</template>

<style scoped>
.dark :deep(.shiki span) {
color: var(--shiki-dark) !important;
}
</style>
```

### With React
Expand Down
2 changes: 2 additions & 0 deletions docs/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ export default defineNuxtConfig({
{ name: 'Geist Mono', weights: [400, 500, 600], global: true },
],
},

studio: false,
})
Loading
Loading