Skip to content

Commit d84ba02

Browse files
Copilothustcc
andauthored
Add interactive examples page with native T8 rendering (#161)
* Initial plan * Add interactive examples page to site with T8 Syntax viewer Co-authored-by: hustcc <7856674+hustcc@users.noreply.github.com> * Fix unused parameter in custom plugin example Co-authored-by: hustcc <7856674+hustcc@users.noreply.github.com> * Move Examples to top navigation menu as separate route Co-authored-by: hustcc <7856674+hustcc@users.noreply.github.com> * Replace CodeSandbox with native T8 source code rendering Co-authored-by: hustcc <7856674+hustcc@users.noreply.github.com> * Remove unused unmount variable Co-authored-by: hustcc <7856674+hustcc@users.noreply.github.com> * chore: update svg style * Fix dead links in examples pages Co-authored-by: hustcc <7856674+hustcc@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: hustcc <7856674+hustcc@users.noreply.github.com> Co-authored-by: hustcc <i@hust.cc>
1 parent b80c981 commit d84ba02

File tree

7 files changed

+360
-0
lines changed

7 files changed

+360
-0
lines changed

site/.vitepress/config.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const createLangConfig = (lang: string, label: string) => {
1212
nav: [
1313
{ text: 'AI', link: '/chat/index', target: 'chat' },
1414
{ text: 'Tutorial', link: `/${lang}/tutorial/quick-start` },
15+
{ text: 'Examples', link: `/${lang}/examples` },
1516
{ text: 'Syntax', link: `/${lang}/syntax/index` },
1617
{ text: 'API', link: `/${lang}/api/` },
1718
],
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<template>
2+
<div class="t8-example">
3+
<div class="example-header">
4+
<button @click="showCode = !showCode" class="toggle-code-btn">{{ showCode ? 'Hide' : 'Show' }} T8 Syntax</button>
5+
</div>
6+
<div v-if="showCode" class="code-display">
7+
<pre><code>{{ syntax }}</code></pre>
8+
</div>
9+
<div class="render-container" :class="containerClass" ref="container"></div>
10+
</div>
11+
</template>
12+
13+
<script setup lang="ts">
14+
import { ref, onMounted, onBeforeUnmount } from 'vue';
15+
16+
const props = defineProps<{
17+
syntax: string;
18+
mode?: 'streaming' | 'dark' | 'custom-plugin';
19+
containerClass?: string;
20+
}>();
21+
22+
const container = ref<HTMLElement | null>(null);
23+
const showCode = ref(false);
24+
let textInstance: any = null;
25+
26+
onMounted(async () => {
27+
if (!container.value) return;
28+
29+
try {
30+
// Dynamically import T8 from source to avoid SSR issues
31+
const { Text } = await import('../../../../src/index.ts');
32+
33+
textInstance = new Text(container.value);
34+
35+
if (props.mode === 'streaming') {
36+
// Streaming render
37+
(async () => {
38+
let chunk = '';
39+
for (let i = 0; i < props.syntax.length; i += 10) {
40+
chunk += props.syntax.slice(i, i + 10);
41+
textInstance.render(chunk);
42+
await new Promise((resolve) => setTimeout(resolve, 160));
43+
}
44+
})();
45+
} else if (props.mode === 'dark') {
46+
// Dark theme with custom settings
47+
textInstance.theme('dark', { fontSize: 12, lineHeight: 20 }).render(props.syntax);
48+
} else if (props.mode === 'custom-plugin') {
49+
// Custom plugin example
50+
const { createDimensionValue } = await import('../../../../src/plugin/presets/createDimensionValue.ts');
51+
52+
const dimensionValueDescriptor = {
53+
style: () => ({
54+
color: 'red',
55+
fontSize: 19,
56+
}),
57+
tooltip: false,
58+
};
59+
60+
const dimensionPlugin = createDimensionValue(dimensionValueDescriptor, 'overwrite');
61+
textInstance.registerPlugin(dimensionPlugin);
62+
textInstance.render(props.syntax);
63+
} else {
64+
// Default render
65+
textInstance.theme('light').render(props.syntax);
66+
}
67+
} catch (error) {
68+
console.error('Failed to load T8:', error);
69+
}
70+
});
71+
72+
onBeforeUnmount(() => {
73+
if (textInstance) {
74+
textInstance.unmount?.();
75+
}
76+
});
77+
</script>
78+
79+
<style scoped>
80+
.t8-example {
81+
margin: 1.5rem 0;
82+
border: 1px solid var(--vp-c-divider);
83+
border-radius: 8px;
84+
overflow: hidden;
85+
}
86+
87+
.example-header {
88+
display: flex;
89+
justify-content: flex-end;
90+
padding: 0.5rem 1rem;
91+
background-color: var(--vp-c-bg-soft);
92+
border-bottom: 1px solid var(--vp-c-divider);
93+
}
94+
95+
.toggle-code-btn {
96+
padding: 0.375rem 0.75rem;
97+
font-size: 0.875rem;
98+
font-weight: 500;
99+
color: var(--vp-c-brand-1);
100+
background-color: transparent;
101+
border: 1px solid var(--vp-c-brand-1);
102+
border-radius: 4px;
103+
cursor: pointer;
104+
transition: all 0.2s;
105+
}
106+
107+
.toggle-code-btn:hover {
108+
background-color: var(--vp-c-brand-1);
109+
color: var(--vp-c-white);
110+
}
111+
112+
.code-display {
113+
padding: 1rem;
114+
background-color: var(--vp-code-block-bg);
115+
border-bottom: 1px solid var(--vp-c-divider);
116+
max-height: 400px;
117+
overflow: auto;
118+
}
119+
120+
.code-display pre {
121+
margin: 0;
122+
padding: 0;
123+
background: transparent;
124+
}
125+
126+
.code-display code {
127+
font-family: var(--vp-font-family-mono);
128+
font-size: 0.875rem;
129+
line-height: 1.5;
130+
color: var(--vp-code-color);
131+
white-space: pre-wrap;
132+
word-break: break-word;
133+
}
134+
135+
.render-container {
136+
padding: 1.5rem;
137+
min-height: 200px;
138+
background-color: var(--vp-c-bg);
139+
}
140+
141+
.render-container.dark {
142+
background-color: #1a1a1a;
143+
color: #ffffff;
144+
}
145+
</style>

site/.vitepress/theme/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { Theme } from 'vitepress';
44
import DefaultTheme from 'vitepress/theme';
55
import './style.css';
66
import CopyOrDownloadAsMarkdownButtons from './components/CopyOrDownloadAsMarkdownButtons.vue';
7+
import T8Example from './components/T8Example.vue';
78
import { Sandbox } from 'vitepress-plugin-sandpack';
89
import MySandbox from './components/MySandbox.vue';
910
import 'vitepress-plugin-sandpack/dist/style.css';
@@ -17,6 +18,7 @@ export default {
1718
},
1819
enhanceApp({ app }) {
1920
app.component('CopyOrDownloadAsMarkdownButtons', CopyOrDownloadAsMarkdownButtons);
21+
app.component('T8Example', T8Example);
2022
app.component('Sandbox', Sandbox);
2123
app.component('MySandbox', MySandbox);
2224
},

site/en/examples.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
title: Interactive Examples
3+
---
4+
5+
<script setup>
6+
const marketAnalysisSyntax = `# 2024 Smartphone Market Analysis
7+
8+
## Market Overview
9+
10+
Global [smartphone shipments](metric_name) reached [1.2 billion units](metric_value, origin=1200000000) in [2024](time_desc), showing a [modest decline of 2.1%](ratio_value, origin=-0.021, assessment="negative") year-over-year.
11+
12+
The **premium segment** (devices over $800) showed *remarkable* [resilience](trend_desc, assessment="positive"), growing by [5.8%](ratio_value, origin=0.058, assessment="positive"). [Average selling price](other_metric_value) was [$420](metric_value, origin=420, unit="USD").
13+
14+
## Key Findings
15+
16+
1. [Asia-Pacific](dim_value) remains the __largest market__
17+
2. [Premium devices](dim_value) showed **strong growth**
18+
3. Budget segment faced *headwinds*
19+
20+
### Asia-Pacific
21+
22+
[Asia-Pacific](dim_value) remains the largest market with [680 million units](metric_value, origin=680000000) shipped, though this represents a [decline of 180 million units](delta_value, origin=-180000000, assessment="negative") from the previous year.
23+
24+
Key markets:
25+
- [China](dim_value): [320M units](metric_value, origin=320000000) - down [8.5%](ratio_value, origin=-0.085, assessment="negative"), [ranked 1st](rank, detail=[320, 180, 90, 65, 45]) globally, accounting for [47%](contribute_ratio, origin=0.47, assessment="positive") of regional sales
26+
- [India](dim_value): [180M units](metric_value, origin=180000000) - up [12.3%](ratio_value, origin=0.123, assessment="positive"), [ranked 2nd](rank, detail=[320, 180, 90, 65, 45]), representing [3 out of 4](proportion, origin=0.45) of the budget segment
27+
- [Southeast Asia](dim_value): [180M units](metric_value, origin=180000000) - [stable](trend_desc, assessment="equal")
28+
29+
The [gap of 140M units](difference, detail=[200, 180, 160, 140]) between [China](dim_value) and [India](dim_value) is [narrowing](trend_desc, assessment="neutral").
30+
31+
### Market Dynamics
32+
33+
Sales showed [strong correlation](association, detail=[{"x":100,"y":105},{"x":120,"y":128},{"x":150,"y":155}]) with economic indicators. The [distribution](distribution, detail=[15, 25, 35, 15, 10]) was [uneven](anomaly, detail=[15, 18, 20, 65, 22]), with [unexpected concentration](anomaly, detail=[15, 18, 20, 65, 22]) in urban areas.
34+
35+
We observed [clear seasonality](seasonality, detail={"data":[80, 90, 95, 135], "range":[0, 150]}) with [Q4 peaks](seasonality, detail={"data":[80, 90, 95, 135]}) driven by holiday shopping.
36+
37+
For detailed methodology, visit [our research page](https://example.com/methodology).`;
38+
</script>
39+
40+
# Interactive Examples
41+
42+
Explore comprehensive examples of T8 features and capabilities. Each example demonstrates different aspects of T8's text visualization power and includes the full T8 Syntax source code.
43+
44+
## Example: 2024 Smartphone Market Analysis
45+
46+
This comprehensive example showcases T8's capabilities for rendering data-driven narrative text with rich entity annotations and inline visualizations. The example includes:
47+
48+
- Multiple entity types (metrics, dimensions, trends, ratios, etc.)
49+
- Inline mini-charts (distributions, correlations, seasonality)
50+
- Complex data relationships (rankings, proportions, comparisons)
51+
- Structured markdown with sections and subsections
52+
53+
### Streaming Render
54+
55+
Watch the content render incrementally, simulating real-time data streaming or AI-generated content. Perfect for scenarios where data arrives progressively.
56+
57+
<T8Example :syntax="marketAnalysisSyntax" mode="streaming" />
58+
59+
### Dark Theme with Custom Settings
60+
61+
The same content rendered with a dark theme and custom typography settings (12px font size, 20px line height).
62+
63+
<T8Example :syntax="marketAnalysisSyntax" mode="dark" container-class="dark" />
64+
65+
### Custom Plugin - Styled Dimension Values
66+
67+
This example demonstrates how to customize entity rendering using plugins. Here, dimension values (like country/region names) are styled with custom colors and fonts.
68+
69+
<T8Example :syntax="marketAnalysisSyntax" mode="custom-plugin" />
70+
71+
## Understanding T8 Syntax
72+
73+
The examples above use **T8 Syntax** - a markdown-based declarative language for narrative text visualization. Key features demonstrated:
74+
75+
### Entity Annotations
76+
77+
Entities are marked using bracket notation: `[text](entity_type, properties)`
78+
79+
- `[smartphone shipments](metric_name)` - Metric names
80+
- `[1.2 billion units](metric_value, origin=1200000000)` - Metric values with raw data
81+
- `[2024](time_desc)` - Time descriptions
82+
- `[modest decline of 2.1%](ratio_value, origin=-0.021, assessment="negative")` - Ratios with sentiment
83+
- `[Asia-Pacific](dim_value)` - Dimension values (categories, regions, etc.)
84+
- `[resilience](trend_desc, assessment="positive")` - Trend descriptions
85+
- `[ranked 1st](rank, detail=[320, 180, 90, 65, 45])` - Rankings with data
86+
87+
### Inline Visualizations
88+
89+
- `[distribution](distribution, detail=[15, 25, 35, 15, 10])` - Mini bar charts
90+
- `[strong correlation](association, detail=[...])` - Scatter plots
91+
- `[clear seasonality](seasonality, detail={...})` - Line charts
92+
- `[gap of 140M units](difference, detail=[200, 180, 160, 140])` - Difference indicators
93+
94+
### Markdown Formatting
95+
96+
Standard markdown syntax is supported:
97+
98+
- `**bold**` for emphasis
99+
- `*italic*` for subtle emphasis
100+
- `__underline__` for highlighting
101+
- Headers (`#`, `##`, `###`) for structure
102+
- Lists (numbered and bulleted)
103+
- Links
104+
105+
Learn more in the [T8 Syntax Documentation](/en/syntax/).

site/zh/examples.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
title: 交互式示例
3+
---
4+
5+
<script setup>
6+
const marketAnalysisSyntax = `# 2024 年智能手机市场分析
7+
8+
## 市场概况
9+
10+
全球[智能手机出货量](metric_name)在 [2024 年](time_desc)达到 [12 亿台](metric_value, origin=1200000000),同比显示出[适度下降 2.1%](ratio_value, origin=-0.021, assessment="negative")。
11+
12+
**高端市场**(800 美元以上设备)表现出*显著的*[韧性](trend_desc, assessment="positive"),增长了 [5.8%](ratio_value, origin=0.058, assessment="positive")。[平均售价](other_metric_value)为 [420 美元](metric_value, origin=420, unit="USD")。
13+
14+
## 主要发现
15+
16+
1. [亚太地区](dim_value)仍然是__最大的市场__
17+
2. [高端设备](dim_value)表现出**强劲增长**
18+
3. 预算市场面临*阻力*
19+
20+
### 亚太地区
21+
22+
[亚太地区](dim_value)仍然是最大的市场,出货量为 [6.8 亿台](metric_value, origin=680000000),尽管这代表着比去年[下降了 1.8 亿台](delta_value, origin=-180000000, assessment="negative")。
23+
24+
主要市场:
25+
- [中国](dim_value):[3.2 亿台](metric_value, origin=320000000) - 下降 [8.5%](ratio_value, origin=-0.085, assessment="negative"),全球[排名第 1](rank, detail=[320, 180, 90, 65, 45]),占地区销售额的 [47%](contribute_ratio, origin=0.47, assessment="positive")
26+
- [印度](dim_value):[1.8 亿台](metric_value, origin=180000000) - 增长 [12.3%](ratio_value, origin=0.123, assessment="positive"),[排名第 2](rank, detail=[320, 180, 90, 65, 45]),占预算市场的 [四分之三](proportion, origin=0.45)
27+
- [东南亚](dim_value):[1.8 亿台](metric_value, origin=180000000) - [稳定](trend_desc, assessment="equal")
28+
29+
[中国](dim_value)和[印度](dim_value)之间的 [1.4 亿台差距](difference, detail=[200, 180, 160, 140])正在[缩小](trend_desc, assessment="neutral")。
30+
31+
### 市场动态
32+
33+
销售额与经济指标显示出[强相关性](association, detail=[{"x":100,"y":105},{"x":120,"y":128},{"x":150,"y":155}])。[分布](distribution, detail=[15, 25, 35, 15, 10])是[不均匀的](anomaly, detail=[15, 18, 20, 65, 22]),在城市地区有[意外集中](anomaly, detail=[15, 18, 20, 65, 22])。
34+
35+
我们观察到[明显的季节性](seasonality, detail={"data":[80, 90, 95, 135], "range":[0, 150]}),[第四季度高峰](seasonality, detail={"data":[80, 90, 95, 135]})由假日购物驱动。
36+
37+
有关详细方法,请访问[我们的研究页面](https://example.com/methodology)。`;
38+
</script>
39+
40+
# 交互式示例
41+
42+
探索 T8 功能和特性的综合示例。每个示例展示了 T8 文本可视化能力的不同方面,并包含完整的 T8 语法源代码。
43+
44+
## 示例:2024 年智能手机市场分析
45+
46+
这个综合示例展示了 T8 在渲染具有丰富实体注释和内联可视化的数据驱动叙事文本方面的能力。该示例包括:
47+
48+
- 多种实体类型(指标、维度、趋势、比率等)
49+
- 内联迷你图表(分布、相关性、季节性)
50+
- 复杂的数据关系(排名、比例、比较)
51+
- 带有章节和小节的结构化 Markdown
52+
53+
### 流式渲染
54+
55+
观看内容逐步渲染,模拟实时数据流或 AI 生成的内容。非常适合数据逐步到达的场景。
56+
57+
<T8Example :syntax="marketAnalysisSyntax" mode="streaming" />
58+
59+
### 暗色主题与自定义设置
60+
61+
使用暗色主题和自定义排版设置(12px 字体大小,20px 行高)渲染相同的内容。
62+
63+
<T8Example :syntax="marketAnalysisSyntax" mode="dark" container-class="dark" />
64+
65+
### 自定义插件 - 样式化维度值
66+
67+
此示例展示了如何使用插件自定义实体渲染。在这里,维度值(如国家/地区名称)使用自定义颜色和字体进行样式化。
68+
69+
<T8Example :syntax="marketAnalysisSyntax" mode="custom-plugin" />
70+
71+
## 理解 T8 语法
72+
73+
以上示例使用 **T8 语法** - 一种基于 Markdown 的声明式语言,用于叙事文本可视化。演示的主要功能:
74+
75+
### 实体注释
76+
77+
实体使用括号表示法标记:`[文本](entity_type, properties)`
78+
79+
- `[智能手机出货量](metric_name)` - 指标名称
80+
- `[12 亿台](metric_value, origin=1200000000)` - 带有原始数据的指标值
81+
- `[2024 年](time_desc)` - 时间描述
82+
- `[适度下降 2.1%](ratio_value, origin=-0.021, assessment="negative")` - 带有情感的比率
83+
- `[亚太地区](dim_value)` - 维度值(类别、地区等)
84+
- `[韧性](trend_desc, assessment="positive")` - 趋势描述
85+
- `[排名第 1](rank, detail=[320, 180, 90, 65, 45])` - 带有数据的排名
86+
87+
### 内联可视化
88+
89+
- `[分布](distribution, detail=[15, 25, 35, 15, 10])` - 迷你条形图
90+
- `[强相关性](association, detail=[...])` - 散点图
91+
- `[明显的季节性](seasonality, detail={...})` - 折线图
92+
- `[1.4 亿台差距](difference, detail=[200, 180, 160, 140])` - 差异指示器
93+
94+
### Markdown 格式
95+
96+
支持标准 Markdown 语法:
97+
98+
- `**粗体**` 表示强调
99+
- `*斜体*` 表示轻微强调
100+
- `__下划线__` 表示突出显示
101+
- 标题(`#``##``###`)用于结构
102+
- 列表(编号和项目符号)
103+
- 链接
104+
105+
[T8 语法文档](/zh/syntax/)中了解更多。

src/charts/utils/createSvg.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const createSvg = (container: Element, width: number, height: number): Se
1212
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
1313
svg.style.margin = '0px 4px';
1414
svg.style.transform = 'translate(0px, 0.125em)';
15+
svg.style.display = 'inline-block';
1516

1617
svg.setAttribute('height', String(height));
1718
svg.setAttribute('width', String(width));

src/plugin/presets/createCompare.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ function createArrow(direction: 'up' | 'down', size: number): Element {
7474
svg.setAttribute('height', `${size}px`);
7575
svg.setAttribute('viewBox', '0 0 8 9');
7676
svg.style.marginRight = `${MARGIN_RIGHT}px`;
77+
svg.style.display = 'inline-block';
7778
svg.setAttribute('version', '1.1');
7879

7980
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');

0 commit comments

Comments
 (0)