observable-notebooks

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Observable Notebooks 2.0

Observable Notebooks 2.0

Overview

概述

Observable Notebooks 2.0 is an open-source notebook system for creating interactive documents that combine code, data, and visualization. It features an HTML-based file format, vanilla JavaScript (no more Observable-specific dialect), and a CLI for building static sites.
Observable Notebooks 2.0是一款开源笔记本系统,用于创建结合代码、数据与可视化的交互式文档。它采用基于HTML的文件格式、原生JavaScript(不再使用Observable专属方言),并提供用于构建静态站点的CLI工具。

When to Use This Skill

适用场景

Use this skill when:
  • Creating new Observable notebooks
  • Editing existing notebook files
  • Building and previewing notebooks locally
  • Working with Observable's standard library (Plot, Inputs, D3)
在以下场景中使用本技能:
  • 创建新的Observable notebooks
  • 编辑现有的笔记本文件
  • 本地构建与预览笔记本
  • 使用Observable标准库(Plot、Inputs、D3)

Installation

安装

Install Notebook Kit as a local dependency:
bash
npm add @observablehq/notebook-kit
将Notebook Kit作为本地依赖安装:
bash
npm add @observablehq/notebook-kit

CLI Commands

CLI命令

Preview (Development Server)

预览(开发服务器)

bash
notebooks preview notebook.html
notebooks preview --root ./notebooks
notebooks preview --template template.tmpl notebook.html
Starts a development server with live reload for editing notebooks.
bash
notebooks preview notebook.html
notebooks preview --root ./notebooks
notebooks preview --template template.tmpl notebook.html
启动带有热重载功能的开发服务器,用于编辑笔记本。

Build (Static Site Generation)

构建(静态站点生成)

bash
notebooks build notebook.html
notebooks build --root ./notebooks -- *.html
Generates static HTML in
.observablehq/dist/
by default.
bash
notebooks build notebook.html
notebooks build --root ./notebooks -- *.html
默认在
.observablehq/dist/
目录下生成静态HTML文件。

Download (Convert Existing Notebooks)

下载(转换现有笔记本)

bash
notebooks download https://observablehq.com/@d3/bar-chart > bar-chart.html
Downloads an existing Observable notebook to the local HTML format.
bash
notebooks download https://observablehq.com/@d3/bar-chart > bar-chart.html
将现有Observable笔记本下载为本地HTML格式。

Query (Database Queries)

查询(数据库查询)

bash
notebooks query --database duckdb 'SELECT * FROM data'
Execute and cache database query results.
bash
notebooks query --database duckdb 'SELECT * FROM data'
执行并缓存数据库查询结果。

File Format

文件格式

Notebooks are HTML files with a
<notebook>
root element:
html
<notebook>
  <title>My Notebook</title>

  <script type="text/markdown">
    # Introduction

    This is a markdown cell with interpolation: ${1 + 1}
  </script>

  <script type="module">
    const data = [1, 2, 3, 4, 5];
    display(data);
  </script>

  <script type="module">
    import * as Plot from "npm:@observablehq/plot";
    display(Plot.barY(data).plot());
  </script>

</notebook>
Use four-space indentation inside
<script>
tags (trimmed during parsing).
笔记本是带有
<notebook>
根元素的HTML文件:
html
<notebook>
  <title>My Notebook</title>

  <script type="text/markdown">
    # 简介

    这是一个支持插值的Markdown单元格:${1 + 1}
  </script>

  <script type="module">
    const data = [1, 2, 3, 4, 5];
    display(data);
  </script>

  <script type="module">
    import * as Plot from "npm:@observablehq/plot";
    display(Plot.barY(data).plot());
  </script>

</notebook>
<script>
标签内使用四个空格缩进(解析时会自动去除)。

Cell Types

单元格类型

TypeScript AttributeDescription
JavaScript
type="module"
Standard ES modules,
display()
for output
TypeScript
type="text/x-typescript"
TypeScript with type checking
Markdown
type="text/markdown"
CommonMark with
${...}
interpolation
HTML
type="text/html"
HTML with auto-escaped interpolation
SQL
type="application/sql"
Database queries
TeX
type="application/x-tex"
LaTeX equations
Graphviz
type="text/vnd.graphviz"
DOT diagram notation
Python
type="text/x-python"
Python code (data loaders)
R
type="text/x-r"
R code (data loaders)
Node.js
type="application/vnd.node.javascript"
Node.js data loaders
类型脚本属性描述
JavaScript
type="module"
标准ES模块,使用
display()
输出内容
TypeScript
type="text/x-typescript"
带有类型检查的TypeScript
Markdown
type="text/markdown"
支持
${...}
插值的CommonMark
HTML
type="text/html"
支持自动转义插值的HTML
SQL
type="application/sql"
数据库查询语句
TeX
type="application/x-tex"
LaTeX公式
Graphviz
type="text/vnd.graphviz"
DOT图表示法
Python
type="text/x-python"
Python代码(数据加载器)
R
type="text/x-r"
R代码(数据加载器)
Node.js
type="application/vnd.node.javascript"
Node.js数据加载器

Cell Attributes

单元格属性

  • pinned
    - Displays the cell's source code alongside output
  • hidden
    - Suppresses implicit display (cell still runs)
  • id="123"
    - Unique positive integer for stable editing
  • database="mydb"
    - Specifies database for SQL cells
  • format="json"
    - Output format for data loaders
  • output="varname"
    - Exposes values from non-JavaScript cells
Example:
html
<script type="module" pinned>
  const x = 42;
  display(x);
</script>

<script type="application/sql" database="duckdb" output="results">
  select * from data limit 10
</script>
  • pinned
    - 在输出内容旁显示单元格源代码
  • hidden
    - 隐藏自动输出(单元格仍会运行)
  • id="123"
    - 用于稳定编辑的唯一正整数
  • database="mydb"
    - 为SQL单元格指定数据库
  • format="json"
    - 数据加载器的输出格式
  • output="varname"
    - 暴露非JavaScript单元格的值
示例:
html
<script type="module" pinned>
  const x = 42;
  display(x);
</script>

<script type="application/sql" database="duckdb" output="results">
  select * from data limit 10
</script>

Reactivity

响应式特性

Cells run automatically when referenced variables change, like a spreadsheet:
html
<script type="module">
  const a = 10;
</script>

<script type="module">
  const b = 20;
</script>

<script type="module">
  // This cell re-runs whenever a or b changes
  display(a + b);
</script>
Top-level variables declared in one cell are accessible throughout the notebook.
单元格会在引用的变量发生变化时自动运行,类似电子表格:
html
<script type="module">
  const a = 10;
</script>

<script type="module">
  const b = 20;
</script>

<script type="module">
  // 每当a或b变化时,此单元格会重新运行
  display(a + b);
</script>
在一个单元格中声明的顶级变量可在整个笔记本中访问。

Standard Library

标准库

Core Functions

核心函数

  • display(value)
    - Render values to the page
  • view(input)
    - Display inputs and return value generators
  • FileAttachment(path)
    - Reference local files
  • invalidation
    - Promise for cleanup on cell re-run
  • visibility
    - Wait for cell to become visible
  • width
    - Current page width (reactive)
  • now
    - Current timestamp (reactive)
  • display(value)
    - 将值渲染到页面
  • view(input)
    - 显示输入控件并返回值生成器
  • FileAttachment(path)
    - 引用本地文件
  • invalidation
    - 单元格重新运行时用于清理的Promise
  • visibility
    - 等待单元格变为可见状态
  • width
    - 当前页面宽度(响应式)
  • now
    - 当前时间戳(响应式)

Preloaded Libraries

预加载库

All available without explicit imports:
  • Inputs - Form controls (
    Inputs.range()
    ,
    Inputs.select()
    , etc.)
  • Plot - Charting library (
    Plot.barY()
    ,
    Plot.line()
    , etc.)
  • D3 - Data visualization utilities
  • htl - Hypertext Literal for safe DOM creation
  • tex - LaTeX rendering
以下库无需显式导入即可使用:
  • Inputs - 表单控件(
    Inputs.range()
    Inputs.select()
    等)
  • Plot - 图表库(
    Plot.barY()
    Plot.line()
    等)
  • D3 - 数据可视化工具集
  • htl - 用于安全创建DOM的Hypertext Literal
  • tex - LaTeX渲染工具

Using npm Packages

使用npm包

html
<script type="module">
  import confetti from "npm:canvas-confetti";
  confetti();
</script>
html
<script type="module">
  import confetti from "npm:canvas-confetti";
  confetti();
</script>

Observable Inputs

Observable Inputs

Create interactive controls that automatically update dependent cells:
html
<script type="module">
  const gain = view(Inputs.range([0, 11], {
    value: 5,
    step: 0.1,
    label: "Gain"
  }));
</script>

<script type="module">
  // This cell re-runs when the slider changes
  display(`Current gain: ${gain}`);
</script>
Available inputs:
  • Inputs.button(label)
    - Click trigger
  • Inputs.toggle({label, value})
    - Boolean switch
  • Inputs.checkbox(options, {label})
    - Multi-select
  • Inputs.radio(options, {label})
    - Single select
  • Inputs.range([min, max], {value, step, label})
    - Numeric slider
  • Inputs.select(options, {label, multiple})
    - Dropdown
  • Inputs.text({label, placeholder})
    - Text input
  • Inputs.textarea({label, rows})
    - Multi-line text
  • Inputs.date({label, value})
    - Date picker
  • Inputs.color({label, value})
    - Color picker
  • Inputs.file({label, accept})
    - File upload
  • Inputs.search(data, {label})
    - Search/filter data
  • Inputs.table(data, {columns})
    - Interactive data table
创建可自动更新依赖单元格的交互式控件:
html
<script type="module">
  const gain = view(Inputs.range([0, 11], {
    value: 5,
    step: 0.1,
    label: "增益"
  }));
</script>

<script type="module">
  // 滑块变化时,此单元格会重新运行
  display(`当前增益:${gain}`);
</script>
可用的输入控件:
  • Inputs.button(label)
    - 点击触发器
  • Inputs.toggle({label, value})
    - 布尔开关
  • Inputs.checkbox(options, {label})
    - 多选框
  • Inputs.radio(options, {label})
    - 单选框
  • Inputs.range([min, max], {value, step, label})
    - 数值滑块
  • Inputs.select(options, {label, multiple})
    - 下拉选择框
  • Inputs.text({label, placeholder})
    - 文本输入框
  • Inputs.textarea({label, rows})
    - 多行文本框
  • Inputs.date({label, value})
    - 日期选择器
  • Inputs.color({label, value})
    - 颜色选择器
  • Inputs.file({label, accept})
    - 文件上传控件
  • Inputs.search(data, {label})
    - 数据搜索/筛选控件
  • Inputs.table(data, {columns})
    - 交互式数据表格

Observable Plot

Observable Plot

Create charts with the grammar of graphics:
html
<script type="module">
  const data = [
    {year: 2020, value: 10},
    {year: 2021, value: 20},
    {year: 2022, value: 15}
  ];

  display(Plot.plot({
    marks: [
      Plot.barY(data, {x: "year", y: "value"})
    ]
  }));
</script>
Common marks:
  • Plot.dot()
    - Scatter plots
  • Plot.line()
    - Line charts
  • Plot.barX()
    ,
    Plot.barY()
    - Bar charts
  • Plot.areaY()
    - Area charts
  • Plot.rectY()
    - Histograms
  • Plot.text()
    - Labels
  • Plot.ruleX()
    ,
    Plot.ruleY()
    - Reference lines
使用图形语法创建图表:
html
<script type="module">
  const data = [
    {year: 2020, value: 10},
    {year: 2021, value: 20},
    {year: 2022, value: 15}
  ];

  display(Plot.plot({
    marks: [
      Plot.barY(data, {x: "year", y: "value"})
    ]
  }));
</script>
常用标记类型:
  • Plot.dot()
    - 散点图
  • Plot.line()
    - 折线图
  • Plot.barX()
    Plot.barY()
    - 柱状图
  • Plot.areaY()
    - 面积图
  • Plot.rectY()
    - 直方图
  • Plot.text()
    - 文本标签
  • Plot.ruleX()
    Plot.ruleY()
    - 参考线

Loading Data

数据加载

Local Files

本地文件

html
<script type="module">
  const data = await FileAttachment("data.csv").csv({typed: true});
  display(Inputs.table(data));
</script>
Supported formats:
.csv()
,
.json()
,
.tsv()
,
.text()
,
.blob()
,
.arrayBuffer()
,
.image()
,
.xlsx()
,
.zip()
.
html
<script type="module">
  const data = await FileAttachment("data.csv").csv({typed: true});
  display(Inputs.table(data));
</script>
支持的格式:
.csv()
.json()
.tsv()
.text()
.blob()
.arrayBuffer()
.image()
.xlsx()
.zip()

Remote Data

远程数据

html
<script type="module">
  const response = await fetch("https://api.example.com/data");
  const data = await response.json();
  display(data);
</script>
html
<script type="module">
  const response = await fetch("https://api.example.com/data");
  const data = await response.json();
  display(data);
</script>

Database Queries

数据库查询

html
<script type="application/sql" database="duckdb" output="results">
  select * from "data.parquet" limit 100
</script>

<script type="module">
  display(Inputs.table(results));
</script>
html
<script type="application/sql" database="duckdb" output="results">
  select * from "data.parquet" limit 100
</script>

<script type="module">
  display(Inputs.table(results));
</script>

Themes

主题

Set a theme on the notebook element:
html
<notebook theme="dark">
  ...
</notebook>
Built-in themes:
air
,
coffee
,
cotton
,
deep-space
,
glacier
,
ink
,
midnight
,
near-midnight
,
ocean-floor
,
parchment
,
slate
,
stark
,
sun-faded
.
在notebook元素上设置主题:
html
<notebook theme="dark">
  ...
</notebook>
内置主题:
air
coffee
cotton
deep-space
glacier
ink
midnight
near-midnight
ocean-floor
parchment
slate
stark
sun-faded

Page Templates

页面模板

Create custom templates for consistent layouts:
html
<!-- template.tmpl -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="generator" content="Observable Notebook Kit">
  <title>My Site</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <header>My Site Header</header>
  <main></main>
  <footer>My Site Footer</footer>
</body>
</html>
Use with:
notebooks build --template template.tmpl -- *.html
The
<main>
element receives the rendered notebook cells.
创建自定义模板以实现一致的布局:
html
<!-- template.tmpl -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="generator" content="Observable Notebook Kit">
  <title>My Site</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <header>我的站点头部</header>
  <main></main>
  <footer>我的站点底部</footer>
</body>
</html>
使用方式:
notebooks build --template template.tmpl -- *.html
<main>
元素会被渲染后的笔记本单元格填充。

Example: Complete Notebook

示例:完整笔记本

html
<notebook theme="slate">
  <title>Sales Dashboard</title>

  <script type="text/markdown">
    # Sales Dashboard

    Interactive visualization of quarterly sales data.
  </script>

  <script type="module">
    const sales = await FileAttachment("sales.csv").csv({typed: true});
  </script>

  <script type="module">
    const quarter = view(Inputs.select(
      ["Q1", "Q2", "Q3", "Q4"],
      {label: "Quarter", value: "Q1"}
    ));
  </script>

  <script type="module">
    const filtered = sales.filter(d => d.quarter === quarter);

    display(Plot.plot({
      title: `Sales for ${quarter}`,
      marks: [
        Plot.barY(filtered, {
          x: "product",
          y: "revenue",
          fill: "category"
        }),
        Plot.ruleY([0])
      ]
    }));
  </script>

  <script type="module" pinned>
    display(Inputs.table(filtered, {
      columns: ["product", "category", "revenue", "units"]
    }));
  </script>

</notebook>
html
<notebook theme="slate">
  <title>销售仪表盘</title>

  <script type="text/markdown">
    # 销售仪表盘

    季度销售数据的交互式可视化。
  </script>

  <script type="module">
    const sales = await FileAttachment("sales.csv").csv({typed: true});
  </script>

  <script type="module">
    const quarter = view(Inputs.select(
      ["Q1", "Q2", "Q3", "Q4"],
      {label: "季度", value: "Q1"}
    ));
  </script>

  <script type="module">
    const filtered = sales.filter(d => d.quarter === quarter);

    display(Plot.plot({
      title: `${quarter}季度销售数据`,
      marks: [
        Plot.barY(filtered, {
          x: "product",
          y: "revenue",
          fill: "category"
        }),
        Plot.ruleY([0])
      ]
    }));
  </script>

  <script type="module" pinned>
    display(Inputs.table(filtered, {
      columns: ["product", "category", "revenue", "units"]
    }));
  </script>

</notebook>

Resources

资源