From 99c0f758a71266bbeff18d6d9f1a78268ac0250b Mon Sep 17 00:00:00 2001 From: Baptiste Leproux Date: Thu, 23 Apr 2026 12:57:25 +0200 Subject: [PATCH] docs(playground): add airbnb demo --- docs/app/components/Playground.vue | 49 ++++++-- .../app/components/playground/BookingCard.vue | 59 +++++++++ docs/app/components/playground/Facility.vue | 22 ++++ docs/app/components/playground/HostInfo.vue | 28 +++++ .../components/playground/PropertyGallery.vue | 17 +++ docs/app/components/playground/RatingBar.vue | 62 +++++++++ docs/app/components/playground/TwoColumn.vue | 10 ++ docs/app/constants/index.ts | 118 +++++++++++++++++- docs/package.json | 1 + pnpm-lock.yaml | 3 + 10 files changed, 355 insertions(+), 14 deletions(-) create mode 100644 docs/app/components/playground/BookingCard.vue create mode 100644 docs/app/components/playground/Facility.vue create mode 100644 docs/app/components/playground/HostInfo.vue create mode 100644 docs/app/components/playground/PropertyGallery.vue create mode 100644 docs/app/components/playground/RatingBar.vue create mode 100644 docs/app/components/playground/TwoColumn.vue diff --git a/docs/app/components/Playground.vue b/docs/app/components/Playground.vue index 87043e5b..ee180534 100644 --- a/docs/app/components/Playground.vue +++ b/docs/app/components/Playground.vue @@ -7,11 +7,17 @@ import emoji from '@comark/nuxt/plugins/emoji' import mermaid from '@comark/nuxt/plugins/mermaid' import jsonRender from '@comark/nuxt/plugins/json-render' import punctuation from '@comark/nuxt/plugins/punctuation' -import breaks from '@comark/vue/plugins/breaks' +import breaks from '@comark/nuxt/plugins/breaks' import { renderMarkdown } from 'comark/render' import { Splitpanes, Pane } from 'splitpanes' -import { defaultMarkdown } from '~/constants' +import { airbnbMarkdown, playgroundExamples } from '~/constants' +import PropertyGallery from '~/components/playground/PropertyGallery.vue' +import RatingBar from '~/components/playground/RatingBar.vue' +import HostInfo from '~/components/playground/HostInfo.vue' +import Facility from '~/components/playground/Facility.vue' +import TwoColumn from '~/components/playground/TwoColumn.vue' +import BookingCard from '~/components/playground/BookingCard.vue' import { useLocalStorage, watchDebounced } from '@vueuse/core' import type { ComarkTree, ComarkPlugin } from 'comark' import VueJsonPretty from 'vue-json-pretty' @@ -20,7 +26,12 @@ const props = defineProps<{ compact?: boolean }>() -const markdown = ref(defaultMarkdown.trim()) +const selectedExample = ref('airbnb') +const currentExample = computed(() => + playgroundExamples.find(e => e.value === selectedExample.value) ?? playgroundExamples[0]!, +) + +const markdown = ref(airbnbMarkdown.trim()) const tree = ref(null) const parseTime = ref(0) const nodeCount = ref(0) @@ -117,7 +128,7 @@ const parseOptionDefs = [ const activePlugins = computed(() => pluginDefs - .filter(p => pluginToggles.value[p.key]) + .filter(p => pluginToggles.value[p.key as keyof typeof pluginToggles.value]) .map(p => p.factory()), ) @@ -187,15 +198,19 @@ onMounted(() => { nextTick(() => parseMarkdown()) }) +watch(selectedExample, () => { + markdown.value = currentExample.value.content.trim() +}) + function resetComark(): void { - markdown.value = defaultMarkdown.trim() + markdown.value = currentExample.value.content.trim() } const formattedOutput = ref('') -watch(tree, async (t: ComarkTree | null) => { - formattedOutput.value = t ? await renderMarkdown(t) : '' -}, { immediate: true }) +watchEffect(async () => { + formattedOutput.value = tree.value ? await renderMarkdown(tree.value as any) : '' +}) const formattedOutputModel = computed({ get: () => formattedOutput.value, @@ -220,12 +235,20 @@ const isMatch = computed(() => >
+ v-for="plugin in pluginDefs" :key="plugin.key" class="flex items-center gap-2.5 w-full px-2 py-1.5 rounded-md text-sm hover:bg-elevated transition-colors" - @click="pluginToggles[plugin.key] = !pluginToggles[plugin.key] as any" + @click="pluginToggles[plugin.key] = !pluginToggles[plugin.key]" > >
diff --git a/docs/app/components/playground/BookingCard.vue b/docs/app/components/playground/BookingCard.vue new file mode 100644 index 00000000..8f0bf943 --- /dev/null +++ b/docs/app/components/playground/BookingCard.vue @@ -0,0 +1,59 @@ + + + diff --git a/docs/app/components/playground/Facility.vue b/docs/app/components/playground/Facility.vue new file mode 100644 index 00000000..0319c772 --- /dev/null +++ b/docs/app/components/playground/Facility.vue @@ -0,0 +1,22 @@ + + + diff --git a/docs/app/components/playground/HostInfo.vue b/docs/app/components/playground/HostInfo.vue new file mode 100644 index 00000000..91a8f9db --- /dev/null +++ b/docs/app/components/playground/HostInfo.vue @@ -0,0 +1,28 @@ + + + diff --git a/docs/app/components/playground/PropertyGallery.vue b/docs/app/components/playground/PropertyGallery.vue new file mode 100644 index 00000000..364e6049 --- /dev/null +++ b/docs/app/components/playground/PropertyGallery.vue @@ -0,0 +1,17 @@ + diff --git a/docs/app/components/playground/RatingBar.vue b/docs/app/components/playground/RatingBar.vue new file mode 100644 index 00000000..132c7dc4 --- /dev/null +++ b/docs/app/components/playground/RatingBar.vue @@ -0,0 +1,62 @@ + + + diff --git a/docs/app/components/playground/TwoColumn.vue b/docs/app/components/playground/TwoColumn.vue new file mode 100644 index 00000000..743d5565 --- /dev/null +++ b/docs/app/components/playground/TwoColumn.vue @@ -0,0 +1,10 @@ + diff --git a/docs/app/constants/index.ts b/docs/app/constants/index.ts index f6f86e91..ad4deaf1 100644 --- a/docs/app/constants/index.ts +++ b/docs/app/constants/index.ts @@ -1,5 +1,114 @@ +export const airbnbMarkdown = `--- +title: Secluded Log Cabin in the Forest +description: A nature retreat powered by Comark +--- + +::PropertyGallery +#main +![Log cabin surrounded by pine trees](https://picsum.photos/seed/woods/800/500) + +#thumbnails +![Misty lake at sunrise](https://picsum.photos/seed/mountain/400/300) + +![Cozy bedroom with wooden beams](https://picsum.photos/id/1045/400/300) + +![Stone fireplace and lounge area](https://picsum.photos/id/48/400/300) + +![Private deck overlooking the forest](https://picsum.photos/seed/cabin/400/300) +:: + +# Amazing Cabin in the Forest + +Entire cabin · 4 guests · 2 bedrooms · 2 beds · 1 bath + +::RatingBar{rating="4.97" reviews="86"} +:: + +\`\`\`json-render +{ + "type": "HostInfo", + "props": { + "name": "Thomas", + "badge": "Superhost", + "duration": "5 years hosting" + } +} +\`\`\` + +::Facility{icon="i-lucide-flame"} +#title +Wood-burning fireplace + +#description +Nothing beats an evening by the fire after a day of hiking in the surrounding trails. +:: + +::Facility{icon="i-lucide-trees"} +#title +Direct trail access + +#description +Step straight onto marked hiking and mountain bike trails from the cabin's back door. +:: + +::Facility{icon="i-lucide-star"} +#title +Truly off-grid feel + +#description +Peaceful, no neighbours in sight — just birdsong, deer, and open sky. +:: + +--- + +::TwoColumn +#left + +Tucked deep in a **pine and oak forest**, this hand-built log cabin sits beside a private stream at the edge of a national park. Every window frames a different stretch of wilderness. + +Wake up to *mist rolling through the treetops*, brew coffee on the wraparound deck, and spend the day exploring — or do absolutely nothing at all. + +### What's included + +- [x] Wood-burning fireplace & stacked logs +- [x] Fully equipped rustic kitchen +- [x] Fresh linen & wool blankets +- [x] Private deck with outdoor furniture +- [x] BBQ grill & fire pit +- [ ] WiFi (basic signal only) +- [ ] Pets allowed (ask host) + +### House Rules + +| Rule | Details | +| ---- | ------- | +| Check-in | After 4:00 PM | +| Checkout | Before 10:00 AM | +| Max guests | 4 | +| Smoking | Outdoors only | +| Fires | Fire pit use only | + +### Getting Around + +The cabin is reached via a **5 km unpaved forest road** — a 4×4 or high-clearance vehicle is recommended in winter. The nearest village with shops is [15 minutes by car](#). + +:::callout{color="warning" icon="i-lucide-triangle-alert"} +Mobile signal is unreliable past the village. Download offline maps before you arrive. +::: + +> [!TIP] +> Thomas leaves a printed guide with the best swimming spots, sunrise viewpoints, and local forager trails. + +#right + +:::BookingCard{title="Add dates for prices" cta="Check availability"} +::: + +:: +` + // ─── Comark Parser State ─── -export const defaultMarkdown = `--- +export const allFeaturesMarkdown = `--- title: Hello Comark description: A Comark playground --- @@ -84,3 +193,10 @@ console.log(tree.nodes) } \`\`\` ` + +export const playgroundExamples: { label: string, value: string, content: string }[] = [ + { label: 'Airbnb', value: 'airbnb', content: airbnbMarkdown }, + { label: 'All Features', value: 'all-features', content: allFeaturesMarkdown }, +] + +export const defaultMarkdown = airbnbMarkdown diff --git a/docs/package.json b/docs/package.json index 4ec3f854..1041f973 100644 --- a/docs/package.json +++ b/docs/package.json @@ -7,6 +7,7 @@ }, "dependencies": { "@comark/nuxt": "catalog:", + "@vueuse/core": "catalog:", "@monaco-editor/loader": "catalog:", "@nuxt/content": "catalog:", "@nuxt/ui": "catalog:", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9beb4414..c46a515b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -382,6 +382,9 @@ importers: '@vercel/speed-insights': specifier: 'catalog:' version: 2.0.0(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(nuxt@4.4.2(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@25.5.2)(@vue/compiler-sfc@3.5.32)(better-sqlite3@12.6.2)(cac@6.7.14)(db0@0.3.4(better-sqlite3@12.6.2))(eslint@10.2.0(jiti@2.6.1))(ioredis@5.10.0)(lightningcss@1.32.0)(magicast@0.5.2)(meow@13.2.0)(optionator@0.9.4)(rolldown@1.0.0-rc.15)(rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.15)(rollup@4.59.0))(rollup@4.59.0)(terser@5.46.0)(tsx@4.21.0)(typescript@5.9.3)(vite@8.0.8(@types/node@25.5.2)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.2))(react@19.2.5)(svelte@5.55.2)(vue-router@4.6.4(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)) + '@vueuse/core': + specifier: 'catalog:' + version: 14.2.1(vue@3.5.32(typescript@5.9.3)) comark: specifier: workspace:* version: link:../packages/comark