Skip to content
Merged
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
1 change: 1 addition & 0 deletions site/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const createLangConfig = (lang: string, label: string) => {
nav: [
{ text: 'AI', link: '/chat/index', target: 'chat' },
{ text: 'Tutorial', link: `/${lang}/tutorial/quick-start` },
{ text: 'Examples', link: `/${lang}/examples` },
{ text: 'Syntax', link: `/${lang}/syntax/index` },
{ text: 'API', link: `/${lang}/api/` },
],
Expand Down
145 changes: 145 additions & 0 deletions site/.vitepress/theme/components/T8Example.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<template>
<div class="t8-example">
<div class="example-header">
<button @click="showCode = !showCode" class="toggle-code-btn">{{ showCode ? 'Hide' : 'Show' }} T8 Syntax</button>
</div>
<div v-if="showCode" class="code-display">
<pre><code>{{ syntax }}</code></pre>
</div>
<div class="render-container" :class="containerClass" ref="container"></div>
</div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue';

const props = defineProps<{
syntax: string;
mode?: 'streaming' | 'dark' | 'custom-plugin';
containerClass?: string;
}>();

const container = ref<HTMLElement | null>(null);
const showCode = ref(false);
let textInstance: any = null;

onMounted(async () => {
if (!container.value) return;

try {
// Dynamically import T8 from source to avoid SSR issues
const { Text } = await import('../../../../src/index.ts');

textInstance = new Text(container.value);

if (props.mode === 'streaming') {
// Streaming render
(async () => {
let chunk = '';
for (let i = 0; i < props.syntax.length; i += 10) {
chunk += props.syntax.slice(i, i + 10);
textInstance.render(chunk);
await new Promise((resolve) => setTimeout(resolve, 160));
}
})();
} else if (props.mode === 'dark') {
// Dark theme with custom settings
textInstance.theme('dark', { fontSize: 12, lineHeight: 20 }).render(props.syntax);
} else if (props.mode === 'custom-plugin') {
// Custom plugin example
const { createDimensionValue } = await import('../../../../src/plugin/presets/createDimensionValue.ts');

const dimensionValueDescriptor = {
style: () => ({
color: 'red',
fontSize: 19,
}),
tooltip: false,
};

const dimensionPlugin = createDimensionValue(dimensionValueDescriptor, 'overwrite');
textInstance.registerPlugin(dimensionPlugin);
textInstance.render(props.syntax);
} else {
// Default render
textInstance.theme('light').render(props.syntax);
}
} catch (error) {
console.error('Failed to load T8:', error);
}
});

onBeforeUnmount(() => {
if (textInstance) {
textInstance.unmount?.();
}
});
</script>

<style scoped>
.t8-example {
margin: 1.5rem 0;
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
overflow: hidden;
}

.example-header {
display: flex;
justify-content: flex-end;
padding: 0.5rem 1rem;
background-color: var(--vp-c-bg-soft);
border-bottom: 1px solid var(--vp-c-divider);
}

.toggle-code-btn {
padding: 0.375rem 0.75rem;
font-size: 0.875rem;
font-weight: 500;
color: var(--vp-c-brand-1);
background-color: transparent;
border: 1px solid var(--vp-c-brand-1);
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;
}

.toggle-code-btn:hover {
background-color: var(--vp-c-brand-1);
color: var(--vp-c-white);
}

.code-display {
padding: 1rem;
background-color: var(--vp-code-block-bg);
border-bottom: 1px solid var(--vp-c-divider);
max-height: 400px;
overflow: auto;
}

.code-display pre {
margin: 0;
padding: 0;
background: transparent;
}

.code-display code {
font-family: var(--vp-font-family-mono);
font-size: 0.875rem;
line-height: 1.5;
color: var(--vp-code-color);
white-space: pre-wrap;
word-break: break-word;
}

.render-container {
padding: 1.5rem;
min-height: 200px;
background-color: var(--vp-c-bg);
}

.render-container.dark {
background-color: #1a1a1a;
color: #ffffff;
}
</style>
2 changes: 2 additions & 0 deletions site/.vitepress/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { Theme } from 'vitepress';
import DefaultTheme from 'vitepress/theme';
import './style.css';
import CopyOrDownloadAsMarkdownButtons from './components/CopyOrDownloadAsMarkdownButtons.vue';
import T8Example from './components/T8Example.vue';
import { Sandbox } from 'vitepress-plugin-sandpack';
import MySandbox from './components/MySandbox.vue';
import 'vitepress-plugin-sandpack/dist/style.css';
Expand All @@ -17,6 +18,7 @@ export default {
},
enhanceApp({ app }) {
app.component('CopyOrDownloadAsMarkdownButtons', CopyOrDownloadAsMarkdownButtons);
app.component('T8Example', T8Example);
app.component('Sandbox', Sandbox);
app.component('MySandbox', MySandbox);
},
Expand Down
105 changes: 105 additions & 0 deletions site/en/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
title: Interactive Examples
---

<script setup>
const marketAnalysisSyntax = `# 2024 Smartphone Market Analysis

## Market Overview

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.

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").

## Key Findings

1. [Asia-Pacific](dim_value) remains the __largest market__
2. [Premium devices](dim_value) showed **strong growth**
3. Budget segment faced *headwinds*

### Asia-Pacific

[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.

Key markets:
- [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
- [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
- [Southeast Asia](dim_value): [180M units](metric_value, origin=180000000) - [stable](trend_desc, assessment="equal")

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").

### Market Dynamics

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.

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.

For detailed methodology, visit [our research page](https://example.com/methodology).`;
</script>

# Interactive Examples

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.

## Example: 2024 Smartphone Market Analysis

This comprehensive example showcases T8's capabilities for rendering data-driven narrative text with rich entity annotations and inline visualizations. The example includes:

- Multiple entity types (metrics, dimensions, trends, ratios, etc.)
- Inline mini-charts (distributions, correlations, seasonality)
- Complex data relationships (rankings, proportions, comparisons)
- Structured markdown with sections and subsections

### Streaming Render

Watch the content render incrementally, simulating real-time data streaming or AI-generated content. Perfect for scenarios where data arrives progressively.

<T8Example :syntax="marketAnalysisSyntax" mode="streaming" />

### Dark Theme with Custom Settings

The same content rendered with a dark theme and custom typography settings (12px font size, 20px line height).

<T8Example :syntax="marketAnalysisSyntax" mode="dark" container-class="dark" />

### Custom Plugin - Styled Dimension Values

This example demonstrates how to customize entity rendering using plugins. Here, dimension values (like country/region names) are styled with custom colors and fonts.

<T8Example :syntax="marketAnalysisSyntax" mode="custom-plugin" />

## Understanding T8 Syntax

The examples above use **T8 Syntax** - a markdown-based declarative language for narrative text visualization. Key features demonstrated:

### Entity Annotations

Entities are marked using bracket notation: `[text](entity_type, properties)`

- `[smartphone shipments](metric_name)` - Metric names
- `[1.2 billion units](metric_value, origin=1200000000)` - Metric values with raw data
- `[2024](time_desc)` - Time descriptions
- `[modest decline of 2.1%](ratio_value, origin=-0.021, assessment="negative")` - Ratios with sentiment
- `[Asia-Pacific](dim_value)` - Dimension values (categories, regions, etc.)
- `[resilience](trend_desc, assessment="positive")` - Trend descriptions
- `[ranked 1st](rank, detail=[320, 180, 90, 65, 45])` - Rankings with data

### Inline Visualizations

- `[distribution](distribution, detail=[15, 25, 35, 15, 10])` - Mini bar charts
- `[strong correlation](association, detail=[...])` - Scatter plots
- `[clear seasonality](seasonality, detail={...})` - Line charts
- `[gap of 140M units](difference, detail=[200, 180, 160, 140])` - Difference indicators

### Markdown Formatting

Standard markdown syntax is supported:

- `**bold**` for emphasis
- `*italic*` for subtle emphasis
- `__underline__` for highlighting
- Headers (`#`, `##`, `###`) for structure
- Lists (numbered and bulleted)
- Links

Learn more in the [T8 Syntax Documentation](/en/syntax/).
105 changes: 105 additions & 0 deletions site/zh/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
title: 交互式示例
---

<script setup>
const marketAnalysisSyntax = `# 2024 年智能手机市场分析

## 市场概况

全球[智能手机出货量](metric_name)在 [2024 年](time_desc)达到 [12 亿台](metric_value, origin=1200000000),同比显示出[适度下降 2.1%](ratio_value, origin=-0.021, assessment="negative")。

**高端市场**(800 美元以上设备)表现出*显著的*[韧性](trend_desc, assessment="positive"),增长了 [5.8%](ratio_value, origin=0.058, assessment="positive")。[平均售价](other_metric_value)为 [420 美元](metric_value, origin=420, unit="USD")。

## 主要发现

1. [亚太地区](dim_value)仍然是__最大的市场__
2. [高端设备](dim_value)表现出**强劲增长**
3. 预算市场面临*阻力*

### 亚太地区

[亚太地区](dim_value)仍然是最大的市场,出货量为 [6.8 亿台](metric_value, origin=680000000),尽管这代表着比去年[下降了 1.8 亿台](delta_value, origin=-180000000, assessment="negative")。

主要市场:
- [中国](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")
- [印度](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)
- [东南亚](dim_value):[1.8 亿台](metric_value, origin=180000000) - [稳定](trend_desc, assessment="equal")

[中国](dim_value)和[印度](dim_value)之间的 [1.4 亿台差距](difference, detail=[200, 180, 160, 140])正在[缩小](trend_desc, assessment="neutral")。

### 市场动态

销售额与经济指标显示出[强相关性](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])。

我们观察到[明显的季节性](seasonality, detail={"data":[80, 90, 95, 135], "range":[0, 150]}),[第四季度高峰](seasonality, detail={"data":[80, 90, 95, 135]})由假日购物驱动。

有关详细方法,请访问[我们的研究页面](https://example.com/methodology)。`;
</script>

# 交互式示例

探索 T8 功能和特性的综合示例。每个示例展示了 T8 文本可视化能力的不同方面,并包含完整的 T8 语法源代码。

## 示例:2024 年智能手机市场分析

这个综合示例展示了 T8 在渲染具有丰富实体注释和内联可视化的数据驱动叙事文本方面的能力。该示例包括:

- 多种实体类型(指标、维度、趋势、比率等)
- 内联迷你图表(分布、相关性、季节性)
- 复杂的数据关系(排名、比例、比较)
- 带有章节和小节的结构化 Markdown

### 流式渲染

观看内容逐步渲染,模拟实时数据流或 AI 生成的内容。非常适合数据逐步到达的场景。

<T8Example :syntax="marketAnalysisSyntax" mode="streaming" />

### 暗色主题与自定义设置

使用暗色主题和自定义排版设置(12px 字体大小,20px 行高)渲染相同的内容。

<T8Example :syntax="marketAnalysisSyntax" mode="dark" container-class="dark" />

### 自定义插件 - 样式化维度值

此示例展示了如何使用插件自定义实体渲染。在这里,维度值(如国家/地区名称)使用自定义颜色和字体进行样式化。

<T8Example :syntax="marketAnalysisSyntax" mode="custom-plugin" />

## 理解 T8 语法

以上示例使用 **T8 语法** - 一种基于 Markdown 的声明式语言,用于叙事文本可视化。演示的主要功能:

### 实体注释

实体使用括号表示法标记:`[文本](entity_type, properties)`

- `[智能手机出货量](metric_name)` - 指标名称
- `[12 亿台](metric_value, origin=1200000000)` - 带有原始数据的指标值
- `[2024 年](time_desc)` - 时间描述
- `[适度下降 2.1%](ratio_value, origin=-0.021, assessment="negative")` - 带有情感的比率
- `[亚太地区](dim_value)` - 维度值(类别、地区等)
- `[韧性](trend_desc, assessment="positive")` - 趋势描述
- `[排名第 1](rank, detail=[320, 180, 90, 65, 45])` - 带有数据的排名

### 内联可视化

- `[分布](distribution, detail=[15, 25, 35, 15, 10])` - 迷你条形图
- `[强相关性](association, detail=[...])` - 散点图
- `[明显的季节性](seasonality, detail={...})` - 折线图
- `[1.4 亿台差距](difference, detail=[200, 180, 160, 140])` - 差异指示器

### Markdown 格式

支持标准 Markdown 语法:

- `**粗体**` 表示强调
- `*斜体*` 表示轻微强调
- `__下划线__` 表示突出显示
- 标题(`#`、`##`、`###`)用于结构
- 列表(编号和项目符号)
- 链接

在 [T8 语法文档](/zh/syntax/)中了解更多。
1 change: 1 addition & 0 deletions src/charts/utils/createSvg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const createSvg = (container: Element, width: number, height: number): Se
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.style.margin = '0px 4px';
svg.style.transform = 'translate(0px, 0.125em)';
svg.style.display = 'inline-block';

svg.setAttribute('height', String(height));
svg.setAttribute('width', String(width));
Expand Down
1 change: 1 addition & 0 deletions src/plugin/presets/createCompare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ function createArrow(direction: 'up' | 'down', size: number): Element {
svg.setAttribute('height', `${size}px`);
svg.setAttribute('viewBox', '0 0 8 9');
svg.style.marginRight = `${MARGIN_RIGHT}px`;
svg.style.display = 'inline-block';
svg.setAttribute('version', '1.1');

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