Skip to content

Commit

Permalink
feat(playground): languages and themes switching (#3)
Browse files Browse the repository at this point in the history
Co-authored-by: L33Z22L11 <[email protected]>
  • Loading branch information
KazariEX and L33Z22L11 authored Oct 10, 2024
1 parent 88d1046 commit 3f49775
Show file tree
Hide file tree
Showing 12 changed files with 883 additions and 564 deletions.
65 changes: 61 additions & 4 deletions playground/app/app.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,63 @@
<script lang="ts" setup>
import { type BundledLanguage, bundledLanguages, type BundledTheme, bundledThemes } from "shiki";
import pkg from "../../package.json";
const repository = new URL(pkg.repository, "https://github.com").href;
const version = "v" + pkg.version;
const langNames = Object.keys(bundledLanguages).sort((a, b) => a.localeCompare(b));
const themeNames = Object.keys(bundledThemes).sort((a, b) => a.localeCompare(b));
const lang = ref<BundledLanguage>("typescript");
const lightTheme = ref<BundledTheme>("catppuccin-latte");
const darkTheme = ref<BundledTheme>("one-dark-pro");
const themes = computed(() => ({
light: lightTheme.value,
dark: darkTheme.value
}));
</script>

<template>
<div m="2">
<theme-switch />
<plain-shiki />
</div>
<header
flex="~ items-center justify-between"
m="x-auto y-4"
p="x-4"
max-w="screen-lg"
>
<hgroup flex="~ gap-2 items-center">
<h1 font="bold" text="5">Plain Shiki Playground</h1>
<span
p="x-1 y-.5"
b="rounded-1"
bg="primary op-20"
font="mono"
text="3 primary"
>{{ version }}</span>
</hgroup>
<nav flex="~ gap-2">
<plain-button as="a" icon="ph:github-logo" title="GitHub" :href="repository"/>
<theme-button mode="light" icon="solar:sun-2-outline"/>
<theme-button mode="system" icon="solar:monitor-outline"/>
<theme-button mode="dark" icon="solar:moon-outline"/>
</nav>
</header>
<main
m="x-auto"
p="x-4"
max-w="screen-lg"
>
<div b="1 solid gray op-40 rounded-md">
<div
flex="~ gap-2 items-center"
p="x-4 y-1"
b-b="~ solid gray op-40"
>
<plain-select :items="langNames" v-model="lang"/>
<plain-select :items="themeNames" v-model="lightTheme"/>
<plain-select :items="themeNames" v-model="darkTheme"/>
</div>
<plain-shiki :lang :themes/>
</div>
</main>
</template>
6 changes: 5 additions & 1 deletion playground/app/assets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ body {
-webkit-font-smoothing: antialiased;
text-size-adjust: 100%;
font-family: var(--font);
}
}

a {
color: inherit;
}
33 changes: 33 additions & 0 deletions playground/app/components/plain-button.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script lang="ts" setup>
const { as = "button" } = defineProps<{
as?: string;
icon: string;
}>();
const attrs = computed(() => (as === "a" ? {
rel: "noopener noreferrer",
target: "_blank"
} : {}));
</script>

<template>
<component
:is="as"
v-bind="attrs"
grid="~ place-items-center"
size="9"
b="1 solid gray op-40 rounded-md"
bg="transparent"
hover:bg="gray op-20"
un-text="4.5"
cursor="pointer"
>
<iconify :name="icon"/>
</component>
</template>

<style scoped>
.is-checked {
--uno: outline-primary outline outline-2 outline-offset--1;
}
</style>
67 changes: 67 additions & 0 deletions playground/app/components/plain-select.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<script lang="ts" setup>
defineProps<{
items: string[];
}>();
const modelValue = defineModel<string>();
</script>

<template>
<select-root v-model="modelValue">
<select-trigger
flex="inline items-center gap-1.5"
h="8"
w="45"
outline="none"
bg="inherit"
font="mono"
text="sm nowrap truncate"
cursor="pointer"
>
<select-icon flex="~" text="3 gray">
<iconify name="fa6-solid:chevron-down"/>
</select-icon>
<select-value />
</select-trigger>
<select-portal>
<select-content
class="select-content"
p="y-2"
b="~ solid gray op-40 rounded-md"
backdrop="blur-6"
font="mono"
position="popper"
>
<select-scroll-up-button flex="~ justify-center" text="3 gray">
<iconify name="fa6-solid:chevron-up"/>
</select-scroll-up-button>
<select-viewport>
<select-item
v-for="item, i in items"
:key="i"
class="select-item"
p="x-3.5"
leading="6"
text="sm"
:value="item"
>
<select-item-text>{{ item }}</select-item-text>
</select-item>
</select-viewport>
<select-scroll-down-button flex="~ justify-center" text="3 gray">
<iconify name="fa6-solid:chevron-down"/>
</select-scroll-down-button>
</select-content>
</select-portal>
</select-root>
</template>

<style>
.select-content {
min-width: var(--radix-select-trigger-width);
max-height: var(--radix-select-content-available-height);
}
.select-item[data-highlighted] {
--uno: outline-none text-primary bg-gray bg-op-30;
}
</style>
30 changes: 14 additions & 16 deletions playground/app/components/plain-shiki.vue
Original file line number Diff line number Diff line change
@@ -1,33 +1,31 @@
<script lang="ts" setup>
import type { BundledLanguage, BundledTheme } from "shiki";
import example from "~/assets/example.ts?raw";
const { lang, themes } = defineProps<{
lang: BundledLanguage;
themes: Record<string, BundledTheme>;
}>();
const editorEl = useTemplateRef("editor");
usePlainShiki(editorEl, {
lang: "ts",
themes: {
light: "catppuccin-latte",
dark: "one-dark-pro"
}
lang: () => lang,
themes: () => themes
});
</script>

<template>
<div
ref="editor"
class="plain-shiki"
p="x-3 y-2"
b="1 solid gray op-40 rounded-md"
overflow="x-auto"
p="x-4 y-3"
outline="none"
font="mono"
whitespace="break-spaces"
lh="6"
text="4"
leading="6"
text="nowrap"
contenteditable
v-html="example"
></div>
</template>

<style>
.plain-shiki {
font-family: consolas, var(--font);
}
</style>
</template>
21 changes: 6 additions & 15 deletions playground/app/components/theme-button.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts" setup>
const props = defineProps<{
const { mode } = defineProps<{
mode: string;
icon: string;
}>();
Expand All @@ -8,32 +8,23 @@
function setColorMode() {
tryStartViewTransition(() => {
colorMode.preference = props.mode;
colorMode.preference = mode;
});
}
</script>

<template>
<button
grid="~ place-items-center"
size="10"
b="1 solid gray op-40 rounded-md"
bg="transparent"
text="5"
transition="250"
cursor="pointer"
<plain-button
:icon
:class="{
[`is-checked`]: colorMode.preference === mode
}"
@click="setColorMode"
>
<iconify :name="icon"/>
</button>
/>
</template>

<style scoped>
.is-checked {
outline: 2px solid rgb(79 155 122);
outline-offset: -1px;
--uno: outline-primary outline outline-2 outline-offset--1;
}
</style>
7 changes: 0 additions & 7 deletions playground/app/components/theme-switch.vue

This file was deleted.

31 changes: 24 additions & 7 deletions playground/app/composables/usePlainShiki.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,48 @@
import { createPlainShiki, type CreatePlainShikiReturns, type MountPlainShikiOptions } from "plain-shiki";
import { type BundledLanguage, createHighlighter, createJavaScriptRegexEngine } from "shiki";
import {
type BundledLanguage,
bundledLanguages,
type BundledTheme,
bundledThemes,
createHighlighterCore,
createJavaScriptRegexEngine,
type HighlighterCore
} from "shiki";

export type UsePlainShikiOptions = Omit<MountPlainShikiOptions, "lang"> & {
export type UsePlainShikiOptions = Omit<MountPlainShikiOptions, "lang" | "themes"> & {
lang: MaybeRefOrGetter<BundledLanguage>;
themes: MaybeRefOrGetter<Record<string, BundledTheme>>;
};

let shiki: HighlighterCore;

export default function(el: MaybeRefOrGetter<HTMLElement | null>, options: UsePlainShikiOptions) {
const target = toRef(el);
const lang = toRef(options.lang);
const themes = toRef(options.themes);

let plain: CreatePlainShikiReturns;
let ctx: ReturnType<(typeof plain)["mount"]>;

const { trigger } = watchTriggerable([target, lang], () => {
const { trigger } = watchTriggerable([target, lang, themes], async () => {
ctx?.dispose();

if (target.value) {
await shiki?.loadLanguage(bundledLanguages[lang.value]);
for (const theme of Object.values(themes.value)) {
await shiki?.loadTheme(bundledThemes[theme]);
}

ctx = plain?.mount(target.value, {
...options,
lang: lang.value
lang: lang.value,
themes: themes.value
});
}
});

tryOnMounted(async () => {
const shiki = await createHighlighter({
langs: ["html", "css", "js", "ts"],
themes: Object.values(options.themes ?? {}).filter((theme) => theme !== void 0),
shiki ??= await createHighlighterCore({
engine: createJavaScriptRegexEngine()
});

Expand Down
3 changes: 2 additions & 1 deletion playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export default defineNuxtConfig({
"@nuxt/icon",
"@nuxtjs/color-mode",
"@unocss/nuxt",
"@vueuse/nuxt"
"@vueuse/nuxt",
"radix-vue/nuxt"
],
colorMode: {
classSuffix: ""
Expand Down
7 changes: 4 additions & 3 deletions playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
},
"dependencies": {
"@vueuse/core": "^11.1.0",
"radix-vue": "^1.9.7",
"vue": "^3.5.11",
"vue-router": "^4.4.5"
},
"devDependencies": {
"@nuxt/icon": "^1.5.2",
"@nuxt/icon": "^1.5.5",
"@nuxtjs/color-mode": "^3.5.1",
"@unocss/nuxt": "^0.63.2",
"@unocss/nuxt": "^0.63.4",
"@vueuse/nuxt": "^11.1.0",
"nuxt": "^3.13.2",
"unocss": "^0.63.2"
"unocss": "^0.63.4"
}
}
10 changes: 9 additions & 1 deletion playground/uno.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { defineConfig, presetAttributify, presetUno } from "unocss";
import { defineConfig, presetAttributify, presetUno, transformerDirectives } from "unocss";

export default defineConfig({
presets: [
presetUno(),
presetAttributify()
],
theme: {
colors: {
primary: "hsl(154deg 32% 46%)"
}
},
transformers: [
transformerDirectives()
]
});
Loading

0 comments on commit 3f49775

Please sign in to comment.