Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
95ea22e
Initial plan
Copilot Aug 22, 2025
136118a
Add YAML support to markdown package and compiler
Copilot Aug 22, 2025
dfe3d05
Add documentation and examples for YAML support
Copilot Aug 22, 2025
88ec312
Replace useYaml with pluginFormat for granular control and remove doc…
Copilot Aug 22, 2025
8543f53
Merge remote-tracking branch 'origin/main' into copilot/fix-743245ab-…
Copilot Aug 22, 2025
9ae5e46
whitespace options
danmarshall Aug 23, 2025
a312653
Remove legacy flaggableJsonPlugin function as requested
Copilot Aug 23, 2025
9ee2656
Add YAML support to mermaid plugin fence parsing
Copilot Aug 23, 2025
5e4e30c
Exclude js-yaml from markdown bundle following css-tree pattern
Copilot Aug 23, 2025
2f3b08e
Add js-yaml to vscode extension following css-tree pattern
Copilot Aug 23, 2025
b55d8fa
Add js-yaml to sandbox getDependencies() following css-tree pattern
Copilot Aug 23, 2025
b38f732
Add js-yaml to remaining getDependencies() methods in UMD bundles
Copilot Aug 23, 2025
7bcee13
Revert changes to generated UMD files as requested
Copilot Aug 23, 2025
28931f2
Merge branch 'main' of https://github.com/microsoft/chartifact into c…
Copilot Aug 24, 2025
ad98d44
rename tabulator
danmarshall Aug 24, 2025
fa6e986
add sales report demo
danmarshall Aug 24, 2025
e7aecba
rebuild
danmarshall Aug 24, 2025
af3f7da
undo primer
danmarshall Aug 24, 2025
03dd242
use json for tabulator
danmarshall Aug 24, 2025
d7e67e2
MermaidProps extends OptionalVariableControl
danmarshall Aug 24, 2025
d6d5d3a
rebuild
danmarshall Aug 24, 2025
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
46 changes: 46 additions & 0 deletions docs/YAML_SUPPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# YAML Support

The chartifact markdown package now supports YAML as an alternative to JSON in all plugin blocks.

## Quick Start

Instead of using `json` prefix, you can now use `yaml`:

```yaml vega-lite
$schema: "https://vega.github.io/schema/vega-lite/v5.json"
description: "A simple bar chart"
data:
values:
- category: "A"
amount: 28
- category: "B"
amount: 55
mark: "bar"
encoding:
x:
field: "category"
type: "nominal"
y:
field: "amount"
type: "quantitative"
```

## Supported Formats

All plugins support both JSON and YAML:
- `yaml vega` / `json vega`
- `yaml vega-lite` / `json vega-lite`
- `yaml textbox` / `json textbox`
- `yaml slider` / `json slider`
- `yaml dropdown` / `json dropdown`
- `yaml checkbox` / `json checkbox`
- And all other plugins...

## Benefits

- More readable and concise syntax
- Better for complex nested structures
- Familiar format for configuration files
- Full backward compatibility with JSON

See the [full documentation](./yaml-support-docs.md) for detailed examples and migration guide.
98 changes: 98 additions & 0 deletions docs/assets/examples/markdown/yaml/json-vs-yaml.idoc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# JSON vs YAML Comparison

This document shows the same functionality implemented in both JSON and YAML to demonstrate the differences.

## JSON Version

```json vega-lite
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "Sales by quarter",
"data": {
"values": [
{"quarter": "Q1", "sales": 120000, "profit": 15000},
{"quarter": "Q2", "sales": 135000, "profit": 18000},
{"quarter": "Q3", "sales": 142000, "profit": 22000},
{"quarter": "Q4", "sales": 158000, "profit": 28000}
]
},
"mark": {
"type": "bar",
"color": "#2E86AB"
},
"encoding": {
"x": {
"field": "quarter",
"type": "nominal",
"axis": {"title": "Quarter"}
},
"y": {
"field": "sales",
"type": "quantitative",
"axis": {"title": "Sales ($)", "format": "$,.0f"}
},
"tooltip": [
{"field": "quarter", "type": "nominal"},
{"field": "sales", "type": "quantitative", "format": "$,.0f"},
{"field": "profit", "type": "quantitative", "format": "$,.0f"}
]
}
}
```

## YAML Version

```yaml vega-lite
$schema: "https://vega.github.io/schema/vega-lite/v5.json"
description: "Sales by quarter"
data:
values:
- quarter: "Q1"
sales: 120000
profit: 15000
- quarter: "Q2"
sales: 135000
profit: 18000
- quarter: "Q3"
sales: 142000
profit: 22000
- quarter: "Q4"
sales: 158000
profit: 28000
mark:
type: "bar"
color: "#2E86AB"
encoding:
x:
field: "quarter"
type: "nominal"
axis:
title: "Quarter"
y:
field: "sales"
type: "quantitative"
axis:
title: "Sales ($)"
format: "$,.0f"
tooltip:
- field: "quarter"
type: "nominal"
- field: "sales"
type: "quantitative"
format: "$,.0f"
- field: "profit"
type: "quantitative"
format: "$,.0f"
```

## Key Differences

| Aspect | JSON | YAML |
|--------|------|------|
| Syntax | Uses brackets `{}` and commas | Uses indentation and dashes |
| Readability | More verbose | More concise and readable |
| Data arrays | `[{"key": "value"}]` | `- key: "value"` |
| Nesting | Bracket-based | Indentation-based |
| Quotes | Required for all strings | Optional for simple strings |

Both versions produce identical functionality - choose the format that works best for your team and use case!
87 changes: 87 additions & 0 deletions docs/assets/examples/markdown/yaml/weather-dashboard.idoc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# YAML Example Document

This document demonstrates YAML syntax support in chartifact.

```yaml vega
$schema: "https://vega.github.io/schema/vega/v5.json"
description: "Interactive temperature dashboard"
signals:
- name: "selectedCity"
value: "New York"
- name: "temperature"
value: 22
- name: "showGrid"
value: true
data:
- name: "weather"
values:
- city: "New York"
temperature: 22
humidity: 65
- city: "Los Angeles"
temperature: 28
humidity: 45
- city: "Chicago"
temperature: 18
humidity: 70
```

## User Controls

Select a city to view its weather data:

```yaml dropdown
variableId: "selectedCity"
value: "New York"
label: "Choose a city"
options:
- "New York"
- "Los Angeles"
- "Chicago"
```

Adjust the temperature:

```yaml slider
variableId: "temperature"
value: 22
label: "Temperature (°C)"
min: -10
max: 40
step: 1
```

Toggle grid display:

```yaml checkbox
variableId: "showGrid"
value: true
label: "Show grid lines"
```

## Weather Chart

```yaml vega-lite
$schema: "https://vega.github.io/schema/vega-lite/v5.json"
description: "Temperature by city"
data:
name: "weather"
mark:
type: "bar"
color: "#1f77b4"
encoding:
x:
field: "city"
type: "nominal"
axis:
title: "City"
y:
field: "temperature"
type: "quantitative"
axis:
title: "Temperature (°C)"
grid:
signal: "showGrid"
```

This example shows how YAML makes the configuration more readable and easier to maintain compared to JSON.
17 changes: 15 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions packages/compiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,9 @@
"url": "https://github.com/microsoft/chartifact/issues"
},
"homepage": "https://github.com/microsoft/chartifact#readme",
"description": ""
}
"description": "",
"dependencies": {
"@types/js-yaml": "^4.0.9",
"js-yaml": "^4.1.0"
}
}
22 changes: 17 additions & 5 deletions packages/compiler/src/md.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Plugins } from '@microsoft/chartifact-markdown';
import { VegaScope } from './scope.js';
import { createSpecWithVariables } from './spec.js';
import { defaultCommonOptions } from 'common';
import * as yaml from 'js-yaml';

const defaultJsonIndent = 2;

Expand All @@ -22,11 +23,20 @@ function jsonWrap(type: string, content: string) {
return tickWrap('json ' + type, content);
}

function yamlWrap(type: string, content: string) {
return tickWrap('yaml ' + type, content);
}

function chartWrap(spec: VegaSpec | VegaLiteSpec) {
const chartType = getChartType(spec);
return jsonWrap(chartType, JSON.stringify(spec, null, defaultJsonIndent));
}

function chartWrapYaml(spec: VegaSpec | VegaLiteSpec) {
const chartType = getChartType(spec);
return yamlWrap(chartType, yaml.dump(spec, { indent: defaultJsonIndent }));
}

function mdContainerWrap(classname: string, id: string, content: string) {
return `::: ${classname} {#${id}}
${content}
Expand All @@ -35,10 +45,12 @@ ${content}

export interface TargetMarkdownOptions {
extraNewlineCount?: number;
useYaml?: boolean;
}

const defaultOptions: TargetMarkdownOptions = {
extraNewlineCount: 1,
useYaml: false,

@danmarshall danmarshall Aug 22, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot There should be more granularity to useYaml: for example, we generally want json for vega plugins. so instead of a prop named useYaml: boolean lets have a prop named pluginFormat that takes a map of plugin names to "json" | "yaml". so we can add more serializers in the future. there should be a wildcard. and we will have a default that should be mixed in. the default is {"*": "yaml", "vega": "json", "vega-lite": "json"}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced useYaml: boolean with granular pluginFormat: Record<string, "json" | "yaml"> as requested. Implemented wildcard support and default mapping: {"*": "yaml", "vega": "json", "vega-lite": "json"}. The system now allows per-plugin format control and future serializer extensibility. (commit 88ec312)

};

export function targetMarkdown(page: InteractiveDocument, options?: TargetMarkdownOptions) {
Expand Down Expand Up @@ -68,14 +80,14 @@ export function targetMarkdown(page: InteractiveDocument, options?: TargetMarkdo
const vegaScope = dataLoaderMarkdown(dataLoaders.filter(dl => dl.type !== 'spec'), variables, tableElements);

for (const dataLoader of dataLoaders.filter(dl => dl.type === 'spec')) {
mdSections.push(chartWrap(dataLoader.spec));
mdSections.push(finalOptions.useYaml ? chartWrapYaml(dataLoader.spec) : chartWrap(dataLoader.spec));
}

for (const group of page.groups) {
mdSections.push(mdContainerWrap(
defaultCommonOptions.groupClassName,
group.groupId,
groupMarkdown(group, variables, vegaScope, page.resources)
groupMarkdown(group, variables, vegaScope, page.resources, finalOptions.useYaml)
));
}

Expand All @@ -97,7 +109,7 @@ export function targetMarkdown(page: InteractiveDocument, options?: TargetMarkdo

if (vegaScope.spec.data || vegaScope.spec.signals) {
//spec is towards the top of the markdown file
mdSections.unshift(chartWrap(vegaScope.spec));
mdSections.unshift(finalOptions.useYaml ? chartWrapYaml(vegaScope.spec) : chartWrap(vegaScope.spec));
}

if (page.notes) {
Expand Down Expand Up @@ -152,7 +164,7 @@ function dataLoaderMarkdown(dataSources: DataSource[], variables: Variable[], ta

type pluginSpecs = Plugins.CheckboxSpec | Plugins.DropdownSpec | Plugins.ImageSpec | Plugins.MermaidSpec | Plugins.PresetsSpec | Plugins.SliderSpec | Plugins.TabulatorSpec | Plugins.TextboxSpec;

function groupMarkdown(group: ElementGroup, variables: Variable[], vegaScope: VegaScope, resources: { charts?: { [chartKey: string]: VegaSpec | VegaLiteSpec } }) {
function groupMarkdown(group: ElementGroup, variables: Variable[], vegaScope: VegaScope, resources: { charts?: { [chartKey: string]: VegaSpec | VegaLiteSpec } }, useYaml = false) {
const mdElements: string[] = [];

const addSpec = (pluginName: Plugins.PluginNames, spec: pluginSpecs, indent = true) => {
Expand All @@ -173,7 +185,7 @@ function groupMarkdown(group: ElementGroup, variables: Variable[], vegaScope: Ve
//add a markdown element (not a chart element) with an image of the spinner at /img/chart-spinner.gif
mdElements.push('![Chart Spinner](/img/chart-spinner.gif)');
} else {
mdElements.push(chartWrap(spec));
mdElements.push(useYaml ? chartWrapYaml(spec) : chartWrap(spec));
}
break;
}
Expand Down
4 changes: 4 additions & 0 deletions packages/markdown/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,9 @@
"homepage": "https://github.com/microsoft/chartifact#readme",
"devDependencies": {
"@types/css-tree": "^2.3.10"
},
"dependencies": {
"@types/js-yaml": "^4.0.9",
"js-yaml": "^4.1.0"
}
}
Loading