Skip to content

Commit

Permalink
refactor(code): refine component structure
Browse files Browse the repository at this point in the history
  • Loading branch information
haoziqaq committed Oct 9, 2024
1 parent fefbde6 commit 470d442
Show file tree
Hide file tree
Showing 23 changed files with 178 additions and 201 deletions.
Empty file modified packages/varlet-cli/lib/node/bin.js
100644 → 100755
Empty file.
1 change: 1 addition & 0 deletions packages/varlet-ui-playground/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const imports = {
'@varlet/ui': usePreviewVersion ? './varlet.esm.js' : 'https://cdn.jsdelivr.net/npm/@varlet/ui/es/varlet.esm.js',
'@varlet/ui/json/area.json': './varlet-area.js',
zod: 'https://cdn.jsdelivr.net/npm/zod/lib/index.mjs',
shiki: 'https://esm.sh/[email protected]',
}

const appFile = 'src/App.vue'
Expand Down
26 changes: 15 additions & 11 deletions packages/varlet-ui/src/code/Code.vue
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
<template>
<div :class="n()" v-html="highlightedCode"></div>
<div :class="classes(n(), [wordWrap, n('--word-wrap')])" v-html="highlightedCode"></div>
</template>

<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import { createNamespace } from '../utils/components'
import { props } from './props'
import { injectHighlighterProvider } from '../highlighter-provider/provide'
import { isFunction } from '@varlet/shared'
const { name, n } = createNamespace('code')
const { name, n, classes } = createNamespace('code')
export default defineComponent({
name,
props,
setup(props) {
const { highlighter, theme } = injectHighlighterProvider()
const highlightedCode = ref('')
const normalizedTheme = computed(() => props.theme ?? theme?.value)
const highlightedCode = ref<string | undefined>(props.code)
const getTheme = computed(() => props.theme || theme)
isFunction(highlighter?.codeToHtml) &&
if (highlighter) {
watch(
() => [props.code, props.language, getTheme.value],
async ([code, lang, theme]) => {
highlightedCode.value = await highlighter.codeToHtml(code || '', { lang, theme })
() => [highlighter.value, props.code, props.language, normalizedTheme.value] as const,
async ([highlighter, code, lang, theme]) => {
if (!highlighter) {
return
}
highlightedCode.value = await highlighter.codeToHtml(code, { lang, theme })
},
{ immediate: true }
)
}
return {
highlightedCode,
n,
classes,
highlightedCode,
}
},
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,21 @@

exports[`test code component props > test code content 1`] = `
"<div class="var-highlighter-provider">
<div class="var-code"><pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#66D9EF;font-style:italic">function</span><span style="color:#A6E22E"> twoSum</span><span style="color:#F8F8F2">(</span><span style="color:#FD971F;font-style:italic">nums</span><span style="color:#F8F8F2">, </span><span style="color:#FD971F;font-style:italic">target</span><span style="color:#F8F8F2">) {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> map </span><span style="color:#F92672">=</span><span style="color:#F92672"> new</span><span style="color:#A6E22E"> Map</span><span style="color:#F8F8F2">();</span></span>
<span class="line"><span style="color:#F92672"> for</span><span style="color:#F8F8F2"> (</span><span style="color:#66D9EF;font-style:italic">let</span><span style="color:#F8F8F2"> i </span><span style="color:#F92672">=</span><span style="color:#AE81FF"> 0</span><span style="color:#F8F8F2">; i </span><span style="color:#F92672">&lt;</span><span style="color:#F8F8F2"> nums.length; i</span><span style="color:#F92672">++</span><span style="color:#F8F8F2">) {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> num </span><span style="color:#F92672">=</span><span style="color:#F8F8F2"> nums[i];</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> theOther </span><span style="color:#F92672">=</span><span style="color:#F8F8F2"> target </span><span style="color:#F92672">-</span><span style="color:#F8F8F2"> num;</span></span>
<span class="line"><span style="color:#F92672"> if</span><span style="color:#F8F8F2"> (map.</span><span style="color:#A6E22E">has</span><span style="color:#F8F8F2">(theOther)) {</span></span>
<span class="line"><span style="color:#F92672"> return</span><span style="color:#F8F8F2"> [map.</span><span style="color:#A6E22E">get</span><span style="color:#F8F8F2">(theOther), i];</span></span>
<span class="line"><span style="color:#F8F8F2"> }</span></span>
<span class="line"><span style="color:#F8F8F2"> map.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(num, i);</span></span>
<span class="line"><span style="color:#F8F8F2"> }</span></span>
<span class="line"><span style="color:#F8F8F2">};</span></span></code></pre>
<div class="var-code"><pre class="shiki vitesse-light" style="background-color:#ffffff;color:#393a34" tabindex="0"><code><span class="line"><span style="color:#B07D48">console</span><span style="color:#999999">.</span><span style="color:#59873A">log</span><span style="color:#999999">(</span><span style="color:#B5695977">'</span><span style="color:#B56959">hello world</span><span style="color:#B5695977">'</span><span style="color:#999999">)</span></span></code></pre>
</div>
</div>"
`;

exports[`test code component props > test code lang 1`] = `
exports[`test code component props > test code language 1`] = `
"<div class="var-highlighter-provider">
<div class="var-code" content="function twoSum(nums, target) {
const map = new Map();
for (let i = 0; i < nums.length; i++) {
const num = nums[i];
const theOther = target - num;
if (map.has(theOther)) {
return [map.get(theOther), i];
}
map.set(num, i);
}
};" lang="javascript"><pre class="shiki nord" style="background-color:#2e3440ff;color:#d8dee9ff" tabindex="0"><code><span class="line"><span></span></span></code></pre>
<div class="var-code"><pre class="shiki vitesse-light" style="background-color:#ffffff;color:#393a34" tabindex="0"><code><span class="line"><span style="color:#998418">print</span><span style="color:#999999">(</span><span style="color:#B5695977">'</span><span style="color:#B56959">Hello Varlet UI</span><span style="color:#B5695977">'</span><span style="color:#999999">)</span></span></code></pre>
</div>
</div>"
`;

exports[`test code component props > test code theme 1`] = `
"<div class="var-highlighter-provider">
<div class="var-code"><pre class="shiki material-theme" style="background-color:#263238;color:#EEFFFF" tabindex="0"><code><span class="line"><span style="color:#C792EA">function</span><span style="color:#82AAFF"> twoSum</span><span style="color:#89DDFF">(</span><span style="color:#EEFFFF;font-style:italic">nums</span><span style="color:#89DDFF">,</span><span style="color:#EEFFFF;font-style:italic"> target</span><span style="color:#89DDFF">)</span><span style="color:#89DDFF"> {</span></span>
<span class="line"><span style="color:#C792EA"> const</span><span style="color:#EEFFFF"> map</span><span style="color:#89DDFF"> =</span><span style="color:#89DDFF"> new</span><span style="color:#82AAFF"> Map</span><span style="color:#F07178">()</span><span style="color:#89DDFF">;</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic"> for</span><span style="color:#F07178"> (</span><span style="color:#C792EA">let</span><span style="color:#EEFFFF"> i</span><span style="color:#89DDFF"> =</span><span style="color:#F78C6C"> 0</span><span style="color:#89DDFF">;</span><span style="color:#EEFFFF"> i</span><span style="color:#89DDFF"> &lt;</span><span style="color:#EEFFFF"> nums</span><span style="color:#89DDFF">.</span><span style="color:#EEFFFF">length</span><span style="color:#89DDFF">;</span><span style="color:#EEFFFF"> i</span><span style="color:#89DDFF">++</span><span style="color:#F07178">) </span><span style="color:#89DDFF">{</span></span>
<span class="line"><span style="color:#C792EA"> const</span><span style="color:#EEFFFF"> num</span><span style="color:#89DDFF"> =</span><span style="color:#EEFFFF"> nums</span><span style="color:#F07178">[</span><span style="color:#EEFFFF">i</span><span style="color:#F07178">]</span><span style="color:#89DDFF">;</span></span>
<span class="line"><span style="color:#C792EA"> const</span><span style="color:#EEFFFF"> theOther</span><span style="color:#89DDFF"> =</span><span style="color:#EEFFFF"> target</span><span style="color:#89DDFF"> -</span><span style="color:#EEFFFF"> num</span><span style="color:#89DDFF">;</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic"> if</span><span style="color:#F07178"> (</span><span style="color:#EEFFFF">map</span><span style="color:#89DDFF">.</span><span style="color:#82AAFF">has</span><span style="color:#F07178">(</span><span style="color:#EEFFFF">theOther</span><span style="color:#F07178">)) </span><span style="color:#89DDFF">{</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic"> return</span><span style="color:#F07178"> [</span><span style="color:#EEFFFF">map</span><span style="color:#89DDFF">.</span><span style="color:#82AAFF">get</span><span style="color:#F07178">(</span><span style="color:#EEFFFF">theOther</span><span style="color:#F07178">)</span><span style="color:#89DDFF">,</span><span style="color:#EEFFFF"> i</span><span style="color:#F07178">]</span><span style="color:#89DDFF">;</span></span>
<span class="line"><span style="color:#89DDFF"> }</span></span>
<span class="line"><span style="color:#EEFFFF"> map</span><span style="color:#89DDFF">.</span><span style="color:#82AAFF">set</span><span style="color:#F07178">(</span><span style="color:#EEFFFF">num</span><span style="color:#89DDFF">,</span><span style="color:#EEFFFF"> i</span><span style="color:#F07178">)</span><span style="color:#89DDFF">;</span></span>
<span class="line"><span style="color:#89DDFF"> }</span></span>
<span class="line"><span style="color:#89DDFF">};</span></span></code></pre>
<div class="var-code"><pre class="shiki material-theme" style="background-color:#263238;color:#EEFFFF" tabindex="0"><code><span class="line"><span style="color:#EEFFFF">console</span><span style="color:#89DDFF">.</span><span style="color:#82AAFF">log</span><span style="color:#EEFFFF">(</span><span style="color:#89DDFF">'</span><span style="color:#C3E88D">hello world</span><span style="color:#89DDFF">'</span><span style="color:#EEFFFF">)</span></span></code></pre>
</div>
</div>"
`;
27 changes: 8 additions & 19 deletions packages/varlet-ui/src/code/__tests__/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,6 @@ import { delay } from '../../utils/test'
import { expect, describe, test } from 'vitest'
import { codeToHtml } from 'shiki'

const code = `function twoSum(nums, target) {
const map = new Map();
for (let i = 0; i < nums.length; i++) {
const num = nums[i];
const theOther = target - num;
if (map.has(theOther)) {
return [map.get(theOther), i];
}
map.set(num, i);
}
};`

test('test code use', () => {
const app = createApp({}).use(Code)
expect(app.component(Code.name)).toBeTruthy()
Expand All @@ -31,34 +19,35 @@ describe('test code component props', () => {
highlighter: {
codeToHtml,
},
theme: 'vitesse-light',
},
slots: {
default: () =>
h(VarCode, {
code,
code: "console.log('hello world')",
language: 'javascript',
theme: 'monokai',
}),
},
})

await delay(300)
await delay(100)
expect(wrapper.html()).toMatchSnapshot()

Check failure on line 34 in packages/varlet-ui/src/code/__tests__/index.spec.js

View workflow job for this annotation

GitHub Actions / test

src/code/__tests__/index.spec.js > test code component props > test code content

Error: Snapshot `test code component props > test code content 1` mismatched - Expected + Received "<div class="var-highlighter-provider"> - <div class="var-code"><pre class="shiki vitesse-light" style="background-color:#ffffff;color:#393a34" tabindex="0"><code><span class="line"><span style="color:#B07D48">console</span><span style="color:#999999">.</span><span style="color:#59873A">log</span><span style="color:#999999">(</span><span style="color:#B5695977">'</span><span style="color:#B56959">hello world</span><span style="color:#B5695977">'</span><span style="color:#999999">)</span></span></code></pre> - </div> + <div class="var-code"></div> </div>" ❯ src/code/__tests__/index.spec.js:34:28
wrapper.unmount()
})

test('test code lang', async () => {
test('test code language', async () => {
const wrapper = mount(VarHighlighterProvider, {
props: {
highlighter: {
codeToHtml,
},
theme: 'vitesse-light',
},
slots: {
default: () =>
h(VarCode, {
content: code,
lang: 'javascript',
code: "print('Hello Varlet UI')",
language: 'python',
}),
},
})
Expand All @@ -78,7 +67,7 @@ describe('test code component props', () => {
slots: {
default: () =>
h(VarCode, {
code,
code: "console.log('hello world')",
language: 'javascript',
theme: 'material-theme',
}),
Expand Down
19 changes: 10 additions & 9 deletions packages/varlet-ui/src/code/code.less
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
:root {
--code-border-radius: 4px;
--code-content-padding: 16px;
--code-font-size: 14px;
--code-line-height: 1.7;
}

.var-code {
border-radius: var(--code-border-radius);
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
line-height: var(--code-line-height);
font-size: var(--code-font-size);

pre {
padding: var(--code-content-padding);
border-radius: var(--code-border-radius);
width: 100%;
height: 100%;
margin: 0;
overflow: auto;
background-color: transparent !important;
}

&--word-wrap pre {
white-space: pre-wrap;
word-break: break-all;
}
}
87 changes: 50 additions & 37 deletions packages/varlet-ui/src/code/docs/en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,54 @@

### Intro

Code component, used to display code blocks and highlight code syntax.
Code Block component, used for code highlighted

### Notes

- Due to package size considerations, Varlet does not include a built-in code highlighter. If you need to use the code block component, please ensure you use the HighlighterProvider component to customize the highlighter.
- Using the HighlighterProvider component, you can set different highlighters for different code blocks. It is recommended to use [Shiki](https://shiki.style/) as the highlighter, as it has built-in support for `codeToHtml` and offers more flexibility in switching languages and themes.
- Due to the size of the package, the component library does not have a built-in code highlighter. Please make sure to use the `HighlighterProvider` component to correctly set the highlighter
- The component library recommends using [Shiki](https://shiki.tmrs.site/) as the highlighter. For the themes and detailed configuration, please refer to the documentation

### Basic Usage
### Install Shiki

```shell
# npm
npm install shiki -S
# yarn
yarn add shiki
# pnpm
pnpm add shiki
```

### Basic Use

```html
<script setup>
import { codeToHtml } from 'shiki'
</script>

<template>
<var-highlighter-provider :highlighter="{ codeToHtml }" theme="vitesse-light">
<var-space direction="column" size="large">
<var-code code="console.log('Hello Varlet UI')" language="javascript" />
<var-code code="print('Hello Varlet UI')" language="python" />
<var-code code="console.log('Hello Varlet UI')" language="javascript" theme="github-light" />
</var-space>
</var-highlighter-provider>
</template>
```

### Word Wrap

Set `word-wrap` to support automatic line wrapping when code overflows.

function createHighlighter() {
return {
codeToHtml,
}
}
```html
<script setup>
import { codeToHtml } from 'shiki'
</script>

<template>
<var-highlighter-provider :highlighter="createHighlighter()" theme="nord">
<var-code code="console.log('varlet')" language="javascript" />
<var-code code="console.log('varlet')" language="javascript" theme='one-dark' />
<var-code code="console.log('varlet')" language="javascript" theme='one-dark-pro' />
<var-highlighter-provider :highlighter="{ codeToHtml }" theme="vitesse-light">
<var-code code="console.log('Hello Varlet UI');console.log('Hello Varlet UI');" language="javascript" word-wrap />
</var-highlighter-provider>
</template>
```
Expand All @@ -37,47 +60,37 @@ function createHighlighter() {

#### Code Props

| Prop | Description | Type | Default |
|------------------|--------------------------------------------------------------|----------------|------------------|
| `code` | Code Snippet | _string_ | `-` |
| `language` | Language | _string_ | `-` |
| `theme` | Theme | _string_ | `-` |
| Prop | Description | Type | Default |
|------------------|-------------------------------------------------------------|-----------------|------------------|
| `code` | Code Snippet | _string_ | `-` |
| `language` | Code Language | _string_ | `-` |
| `theme` | Code Theme | _string_ | `-` |

#### HighlighterProvider Props

| Prop | Description | Type | Default |
| Prop | Description | Type | Default |
|------------------|--------------------------------------------------------------|----------------|------------------|
| `highlighter` | Shader | `Highlighter` | `-` |
| `theme` | Theme | _string_ | `-` |
| `tag` | Tag name | _string_ | `div` |

| `highlighter` | Code Highlighter | `Highlighter` | `-` |
| `theme` | Code Theme | _string_ | `-` |
| `tag` | Custom tag name | _string_ | `div` |

#### Highlighter

| Prop | Description | Type | Default |
| ------ | ------ | ------ | ------ |
| `codeToHtml` | Callback this function when the content, theme, or language changes, and specify the lang and theme options. It will return an HTML string. | `(code: string, options: CodeToHtmlOptions) => Promise<string>` | `-`
| `codeToHtml` | Highlighter function, component highlighter must implement this function | `(code: string, options: CodeToHtmlOptions) => Promise<string>` | `-`

#### CodeToHtmlOptions

| Prop | Description | Type | Default |
| ------ | ------ | ------ | ------ |
| `lang` | language | _string_ | `-` |
| `theme` | theme | _string_ | `-` |

### Slots

#### HighlighterProvider Slots

| Name | Description | SlotProps |
| --- | --- | --- |
| `default` | Component content | `-` |
| `lang` | Code Language | _string_ | `-` |
| `theme` | Code Theme | _string_ | `-` |

### Style Variables

Here are the CSS variables used by the component. Styles can be customized using [StyleProvider](#/en-US/style-provider).

| Variable | Default |
| --- | --- |
| `--code-border-radius` | `4px` |
| `--code-content-padding` | `16px` |
| `--code-line-height` | `1.7` |
| `--code-font-size` | `14px` |
Loading

0 comments on commit 470d442

Please sign in to comment.