☰ GDG /
Docstrings (001–005)
#001 gdtest_minimal #002 gdtest_google #003 gdtest_sphinx #004 gdtest_nodocs #005 gdtest_mixed_docs
Layouts (006–013)
#006 gdtest_src_layout #007 gdtest_python_layout #008 gdtest_lib_layout #009 gdtest_hatch #010 gdtest_setuptools_find #011 gdtest_setup_cfg #012 gdtest_setup_py #013 gdtest_auto_discover
Exports (014–017)
#014 gdtest_no_all #015 gdtest_all_concat #016 gdtest_config_exclude #017 gdtest_auto_exclude
Object Types (018–027)
#018 gdtest_small_class #019 gdtest_big_class #020 gdtest_dataclasses #021 gdtest_enums #022 gdtest_typed_containers #023 gdtest_protocols #024 gdtest_descriptors #025 gdtest_dunders #026 gdtest_nested_class #027 gdtest_constants
Directives (028–032)
#028 gdtest_seealso #029 gdtest_nodoc #030 gdtest_user_guide_auto #031 gdtest_user_guide_sections #032 gdtest_user_guide_subdirs
User Guide (033–038)
#033 gdtest_user_guide_explicit #034 gdtest_user_guide_custom_dir #035 gdtest_user_guide_hyphen #036 gdtest_readme_rst #037 gdtest_index_qmd #038 gdtest_index_md
Landing Pages (039–043)
#039 gdtest_no_readme #040 gdtest_index_wins #041 gdtest_full_extras #042 gdtest_github_contrib #043 gdtest_cli_click
Extras & Config (044–050)
#044 gdtest_cli_nested #045 gdtest_explicit_ref #046 gdtest_kitchen_sink #047 gdtest_name_mismatch #048 gdtest_src_big_class #049 gdtest_google_big_class #050 gdtest_user_guide_cli
Cross-Dimension (051–065)
#051 gdtest_explicit_big_class #052 gdtest_src_no_all #053 gdtest_extras_guide #054 gdtest_google_seealso #055 gdtest_setup_cfg_src #056 gdtest_exclude_cli #057 gdtest_src_explicit_ref #058 gdtest_async_funcs #059 gdtest_generators #060 gdtest_overloads #061 gdtest_abstract_props #062 gdtest_multi_inherit #063 gdtest_slots_class #064 gdtest_frozen_dc #065 gdtest_generics
API Patterns (066–077)
#066 gdtest_context_mgr #067 gdtest_decorators #068 gdtest_exceptions #069 gdtest_reexports #070 gdtest_many_exports #071 gdtest_deep_nesting #072 gdtest_long_docs #073 gdtest_many_guides #074 gdtest_many_big_classes #075 gdtest_flit #076 gdtest_pdm #077 gdtest_namespace
Scale & Stress (078–082)
#078 gdtest_monorepo #079 gdtest_multi_module #080 gdtest_src_legacy #081 gdtest_empty_module #082 gdtest_all_private
Build Systems (083–088)
#083 gdtest_duplicate_all #084 gdtest_badge_readme #085 gdtest_math_docs #086 gdtest_mixed_guide_ext #087 gdtest_unicode_docs #088 gdtest_config_all_on
Edge Cases (089–095)
#089 gdtest_config_display #090 gdtest_config_minimal #091 gdtest_config_parser #092 gdtest_config_extra_keys #093 gdtest_github_icon #094 gdtest_source_branch #095 gdtest_source_path
Config Matrix (096–100)
#096 gdtest_source_title #097 gdtest_source_disabled #098 gdtest_sidebar_disabled #099 gdtest_sidebar_min_items #100 gdtest_sidebar_float
Config Options (101–125)
#101 gdtest_cli_name #102 gdtest_dynamic_false #103 gdtest_parser_google #104 gdtest_parser_sphinx #105 gdtest_display_name #106 gdtest_funding #107 gdtest_authors_multi #108 gdtest_no_darkmode #109 gdtest_exclude_list #110 gdtest_jupyter_kernel #111 gdtest_config_sections #112 gdtest_config_ug_string #113 gdtest_config_ug_list #114 gdtest_config_changelog #115 gdtest_config_reference #116 gdtest_config_combo_a #117 gdtest_config_combo_b #118 gdtest_config_combo_c #119 gdtest_config_combo_d #120 gdtest_config_combo_e #121 gdtest_config_combo_f #122 gdtest_attribution_on #123 gdtest_attribution_off #124 gdtest_rst_versionadded #125 gdtest_rst_deprecated
Docstring Richness (126–150)
#126 gdtest_rst_note #127 gdtest_rst_warning #128 gdtest_rst_tip #129 gdtest_rst_caution #130 gdtest_rst_danger #131 gdtest_rst_important #132 gdtest_rst_mixed_dirs #133 gdtest_sphinx_func_role #134 gdtest_sphinx_class_role #135 gdtest_sphinx_exc_role #136 gdtest_sphinx_meth_role #137 gdtest_sphinx_mixed_roles #138 gdtest_numpy_rich #139 gdtest_google_rich #140 gdtest_sphinx_rich #141 gdtest_docstring_examples #142 gdtest_docstring_notes #143 gdtest_docstring_warnings #144 gdtest_docstring_references #145 gdtest_docstring_seealso #146 gdtest_docstring_math #147 gdtest_docstring_tables #148 gdtest_docstring_combo #149 gdtest_ug_auto #150 gdtest_ug_numbered
UG Variations (151–165)
#151 gdtest_ug_sections_fm #152 gdtest_ug_subdirs #153 gdtest_ug_custom_dir #154 gdtest_ug_deep_nest #155 gdtest_ug_mixed_ext #156 gdtest_ug_many_pages #157 gdtest_ug_explicit_order #158 gdtest_ug_single_page #159 gdtest_ug_no_frontmatter #160 gdtest_ug_with_code #161 gdtest_ug_with_images #162 gdtest_ug_hyphen_dir #163 gdtest_ug_combo #164 gdtest_sec_examples #165 gdtest_sec_tutorials
Custom Sections (166–175)
#166 gdtest_sec_recipes #167 gdtest_sec_blog #168 gdtest_sec_faq #169 gdtest_sec_multi #170 gdtest_sec_navbar_after #171 gdtest_sec_with_ug #172 gdtest_sec_with_ref #173 gdtest_sec_deep #174 gdtest_sec_index_opt #175 gdtest_sec_index_hero
Reference Config (176–185)
#176 gdtest_sec_sidebar_single #177 gdtest_custom_passthrough_navbar #178 gdtest_custom_raw_navbar_after #179 gdtest_custom_mixed_modes #180 gdtest_custom_nested_combo #181 gdtest_custom_basename_output #182 gdtest_custom_nested_output #183 gdtest_custom_missing_dir_combo #184 gdtest_ref_explicit #185 gdtest_ref_members_false
Site Theming (186–195)
#186 gdtest_ref_mixed #187 gdtest_ref_reorder #188 gdtest_ref_sectioned #189 gdtest_ref_single_section #190 gdtest_ref_module_expand #191 gdtest_ref_big_class #192 gdtest_ref_multi_big #193 gdtest_ref_title #194 gdtest_theme_cosmo #195 gdtest_theme_lumen
Stress Tests (196–200)
#196 gdtest_theme_cerulean #197 gdtest_toc_disabled #198 gdtest_toc_depth #199 gdtest_toc_title #200 gdtest_site_combo #201 gdtest_display_badges #202 gdtest_display_authors #203 gdtest_display_funding #204 gdtest_stress_all_config #205 gdtest_stress_all_docstr #206 gdtest_stress_all_ug #207 gdtest_stress_all_sections #208 gdtest_stress_everything #209 gdtest_src_google_seealso #210 gdtest_hatch_nodoc #211 gdtest_pdm_big_class #212 gdtest_flit_enums #213 gdtest_namespace_ug #214 gdtest_ug_subdir_numbered #215 gdtest_homepage_ug #216 gdtest_long_names #217 gdtest_logo #218 gdtest_hero_basic #219 gdtest_hero_readme_badges #220 gdtest_hero_disabled #221 gdtest_hero_custom #222 gdtest_hero_wordmark #223 gdtest_hero_no_logo #224 gdtest_hero_explicit_badges #225 gdtest_hero_index_qmd #226 gdtest_hero_auto_logo #227 gdtest_md_disabled #228 gdtest_md_no_widget #229 gdtest_announce_simple #230 gdtest_announce_dict #231 gdtest_announce_disabled #232 gdtest_gradient_sky #233 gdtest_gradient_peach #234 gdtest_gradient_prism #235 gdtest_gradient_lilac #236 gdtest_gradient_slate #237 gdtest_gradient_honey #238 gdtest_gradient_dusk #239 gdtest_gradient_mint #240 gdtest_gradient_navbar #241 gdtest_gradient_both #242 gdtest_gradient_mixed #243 gdtest_gradient_no_dismiss #244 gdtest_header_text #245 gdtest_header_list #246 gdtest_header_file #247 gdtest_navbar_color #248 gdtest_navbar_color_light #249 gdtest_navbar_color_dark #250 gdtest_navbar_color_same #251 gdtest_navbar_color_split #252 gdtest_kitchen_sink_q #253 gdtest_stress_everything_q #254 gdtest_seealso_desc #255 gdtest_numpy_seealso_desc #256 gdtest_interlinks_prose #257 gdtest_autolink #258 gdtest_skill_default #259 gdtest_skill_curated #260 gdtest_skill_config #261 gdtest_skill_disabled #262 gdtest_skill_rich #263 gdtest_skill_combo #264 gdtest_skill_complex #265 gdtest_i18n_french #266 gdtest_i18n_japanese #267 gdtest_i18n_arabic #268 gdtest_code_cells #269 gdtest_nav_icons #270 gdtest_page_tags #271 gdtest_page_status #272 gdtest_tag_location #273 gdtest_icon_shortcode #274 gdtest_homepage_ug_subdirs #275 gdtest_gt_tables #276 gdtest_scale_to_fit #277 gdtest_scale_min_scale #278 gdtest_homepage_wide #279 gdtest_interlinks_userguide #280 gdtest_code_span_headings #281 gdtest_sec_blog_user_index #282 gdtest_sec_dir_titles #283 gdtest_namespace_src #284 gdtest_auto_include #285 gdtest_no_auto_exclude #286 gdtest_tbl_preview #287 gdtest_tbl_shortcode #288 gdtest_tbl_explorer #289 gdtest_hr_shortcode #290 gdtest_accent_color #291 gdtest_keys_shortcode #292 gdtest_inline_methods #293 gdtest_inline_always #294 gdtest_inline_never #295 gdtest_inline_threshold #296 gdtest_ref_inherited_explicit #297 gdtest_ref_include_inherited #298 gdtest_mock_code #299 gdtest_details_shortcode
299/299 built ⏱ 58.7s 🧪 19/19

gdtest-tbl-preview

A showcase site demonstrating the tbl_preview() function from Great Docs. Each user-guide page exercises a different combination of data sources, table shapes, and display options.

Table preview showcase exercising tbl_preview() with six user-guide pages: basic dict/list-of-dicts previews, Pandas DataFrames, Polars DataFrames, missing-value highlighting (None/NaN/Inf), column subsets and wide tables, and a full-options page showing every parameter. Tests badge rendering (Table/Pandas/Polars), head/tail splitting, dark-mode CSS, HTML escaping, and side-by-side comparison with raw DataFrame output.

Source files
📁 gdtest_tbl_preview/
📄 __init__.py
"""Sample data generators for table preview demos."""

__version__ = "0.1.0"
__all__ = [
    "sample_scores",
    "sample_inventory",
    "sample_wide",
    "sample_missing",
    "sample_types",
]

from .data import (
    sample_scores,
    sample_inventory,
    sample_wide,
    sample_missing,
    sample_types,
)
📄 data.py
"""Functions that generate sample data for preview demos."""

from __future__ import annotations


def sample_scores(n: int = 20) -> dict[str, list]:
    """
    Generate a student scores dataset.

    Parameters
    ----------
    n
        Number of rows.

    Returns
    -------
    dict[str, list]
        Column-oriented dict with name, subject, score, grade, and
        pass/fail columns.

    Examples
    --------
    >>> data = sample_scores(5)
    >>> len(data["name"])
    5
    """
    import random
    random.seed(42)
    names = ["Alice", "Bob", "Charlie", "Diana", "Eve",
             "Frank", "Grace", "Hank", "Iris", "Jack"]
    subjects = ["Math", "Science", "English", "History", "Art"]
    grades = ["A+", "A", "A-", "B+", "B", "B-", "C+", "C", "D", "F"]
    rows_name = [random.choice(names) for _ in range(n)]
    rows_subj = [random.choice(subjects) for _ in range(n)]
    rows_score = [round(random.uniform(40, 100), 1) for _ in range(n)]
    rows_grade = [random.choice(grades) for _ in range(n)]
    rows_pass = [s >= 60.0 for s in rows_score]
    return {
        "name": rows_name,
        "subject": rows_subj,
        "score": rows_score,
        "grade": rows_grade,
        "passed": rows_pass,
    }


def sample_inventory(n: int = 30) -> dict[str, list]:
    """
    Generate a product inventory dataset.

    Parameters
    ----------
    n
        Number of rows.

    Returns
    -------
    dict[str, list]
        Column-oriented dict with product, category, price, stock,
        and rating columns.

    Examples
    --------
    >>> data = sample_inventory(10)
    >>> len(data["product"])
    10
    """
    import random
    random.seed(99)
    products = [
        "Widget", "Gadget", "Doohickey", "Thingamajig",
        "Gizmo", "Whatchamacallit", "Contraption", "Apparatus",
    ]
    categories = ["Electronics", "Tools", "Kitchen", "Garden", "Office"]
    rows_prod = [random.choice(products) for _ in range(n)]
    rows_cat = [random.choice(categories) for _ in range(n)]
    rows_price = [round(random.uniform(5.0, 200.0), 2) for _ in range(n)]
    rows_stock = [random.randint(0, 500) for _ in range(n)]
    rows_rating = [round(random.uniform(1.0, 5.0), 1) for _ in range(n)]
    return {
        "product": rows_prod,
        "category": rows_cat,
        "price": rows_price,
        "stock": rows_stock,
        "rating": rows_rating,
    }


def sample_wide(n_rows: int = 15, n_cols: int = 20) -> dict[str, list]:
    """
    Generate a wide dataset with many columns.

    Parameters
    ----------
    n_rows
        Number of rows.
    n_cols
        Number of columns.

    Returns
    -------
    dict[str, list]
        Column-oriented dict with columns named ``col_001``
        through ``col_{n_cols:03d}``.

    Examples
    --------
    >>> data = sample_wide(5, 8)
    >>> len(data)
    8
    """
    import random
    random.seed(7)
    return {
        f"col_{i+1:03d}": [round(random.gauss(0, 1), 3) for _ in range(n_rows)]
        for i in range(n_cols)
    }


def sample_missing(n: int = 15) -> dict[str, list]:
    """
    Generate a dataset riddled with missing values.

    Parameters
    ----------
    n
        Number of rows.

    Returns
    -------
    dict[str, list]
        Column-oriented dict where roughly 25 percent of values are
        ``None`` or ``float('nan')``.

    Examples
    --------
    >>> data = sample_missing(10)
    >>> None in data["alpha"]
    True
    """
    import random
    import math
    random.seed(13)

    def _maybe_none(val):
        return None if random.random() < 0.25 else val

    return {
        "alpha": [_maybe_none(random.choice(["foo", "bar", "baz"])) for _ in range(n)],
        "beta": [_maybe_none(round(random.gauss(50, 15), 2)) for _ in range(n)],
        "gamma": [
            float("nan") if random.random() < 0.2 else random.randint(1, 100)
            for _ in range(n)
        ],
        "delta": [_maybe_none(random.choice([True, False])) for _ in range(n)],
    }


def sample_types() -> dict[str, list]:
    """
    Generate a dataset that exercises many Python types.

    Returns
    -------
    dict[str, list]
        Six rows with int, float, bool, string, None, and large-number
        columns.

    Examples
    --------
    >>> data = sample_types()
    >>> len(data["integer"])
    6
    """
    return {
        "integer": [0, 1, -42, 1_000_000, 2**31, None],
        "floating": [0.0, 3.14, -2.718, 1e10, float("inf"), float("nan")],
        "boolean": [True, False, True, False, None, True],
        "text": ["hello", "world", "", "café", "<b>bold</b>", None],
        "big_number": [10**18, 10**15, 10**12, 10**9, 10**6, 10**3],
    }
📁 user_guide/
📄 01-basic-preview.qmd
---
title: Basic Preview
---

## Default Settings

The simplest way to use `tbl_preview()` — pass a column-oriented
dict and let the defaults do the work.

```{python}
from great_docs import tbl_preview
from gdtest_tbl_preview import sample_scores

tbl_preview(sample_scores(20))
```

## From a List of Dicts

You can also pass a list of row dicts:

```{python}
rows = [
    {"city": "Tokyo", "pop_m": 37.4, "country": "Japan"},
    {"city": "Delhi", "pop_m": 32.9, "country": "India"},
    {"city": "Shanghai", "pop_m": 29.2, "country": "China"},
    {"city": "São Paulo", "pop_m": 22.4, "country": "Brazil"},
    {"city": "Mexico City", "pop_m": 21.8, "country": "Mexico"},
]
tbl_preview(rows)
```

## With a Caption

```{python}
tbl_preview(
    sample_scores(12),
    caption="Student Performance — Fall 2025",
)
```
📄 02-pandas-tables.qmd
---
title: Pandas Tables
---

## Pandas DataFrame

Pass a Pandas DataFrame directly. The preview auto-detects the
library and shows a **Pandas** badge.

```{python}
import pandas as pd
from great_docs import tbl_preview

df = pd.DataFrame({
    "name": ["Alice", "Bob", "Charlie", "Diana", "Eve",
             "Frank", "Grace", "Hank", "Iris", "Jack",
             "Kate", "Leo", "Mia", "Noah", "Olivia"],
    "department": ["Eng", "Sales", "Eng", "HR", "Sales",
                   "Eng", "HR", "Sales", "Eng", "HR",
                   "Sales", "Eng", "HR", "Sales", "Eng"],
    "salary": [95000, 72000, 88000, 65000, 78000,
              105000, 62000, 81000, 92000, 58000,
              74000, 110000, 67000, 83000, 97000],
    "years": [5, 3, 7, 2, 4, 10, 1, 6, 8, 3, 4, 12, 2, 5, 9],
})

tbl_preview(df)
```

## Custom Head and Tail

Show 8 rows from the top and 3 from the bottom:

```{python}
tbl_preview(df, n_head=8, n_tail=3)
```

## Show All Rows

```{python}
tbl_preview(df, show_all=True)
```
📄 03-polars-tables.qmd
---
title: Polars Tables
---

## Polars DataFrame

Polars DataFrames are detected automatically and show a blue
**Polars** badge with precise dtype labels.

```{python}
import polars as pl
from great_docs import tbl_preview

df = pl.DataFrame({
    "id": range(1, 26),
    "value": [x * 1.1 for x in range(1, 26)],
    "category": ["A", "B", "C", "D", "E"] * 5,
    "flag": [True, False] * 12 + [True],
})

tbl_preview(df)
```

## Head Only (No Tail)

```{python}
tbl_preview(df, n_head=10, n_tail=0)
```
📄 04-missing-values.qmd
---
title: Missing Values
---

## Highlighted Missing Values

By default, `None` and `NaN` values are highlighted in red:

```{python}
from great_docs import tbl_preview
from gdtest_tbl_preview import sample_missing

tbl_preview(sample_missing(15))
```

## Without Highlighting

Turn off missing-value highlighting with `highlight_missing=False`:

```{python}
tbl_preview(sample_missing(15), highlight_missing=False)
```

## Mixed Python Types

Inf, NaN, None, empty strings, HTML-unsafe characters, and large
numbers:

```{python}
from gdtest_tbl_preview import sample_types

tbl_preview(sample_types(), show_all=True)
```
📄 05-column-options.qmd
---
title: Column Options
---

## Column Subset

Select and reorder columns with the `columns` parameter:

```{python}
from great_docs import tbl_preview
from gdtest_tbl_preview import sample_inventory

data = sample_inventory(25)
tbl_preview(data, columns=["product", "price", "rating"])
```

## Wide Table

A table with 20 columns overflows and scrolls horizontally:

```{python}
from gdtest_tbl_preview import sample_wide

tbl_preview(sample_wide(12, 20))
```

## No Row Numbers

```{python}
tbl_preview(
    sample_inventory(10),
    show_row_numbers=False,
)
```

## No Dtype Labels

```{python}
tbl_preview(
    sample_inventory(10),
    show_dtypes=False,
)
```
📄 06-all-options.qmd
---
title: All Options
---

## Minimal Chrome

Turn off every optional element — no row numbers, no dtypes,
no dimension badges:

```{python}
from great_docs import tbl_preview
from gdtest_tbl_preview import sample_scores

tbl_preview(
    sample_scores(8),
    show_row_numbers=False,
    show_dtypes=False,
    show_dimensions=False,
    show_all=True,
)
```

## Full Chrome with Caption

Everything enabled plus a caption:

```{python}
tbl_preview(
    sample_scores(50),
    n_head=10,
    n_tail=5,
    caption="Top & bottom of the class roster",
)
```

## Custom Column Width

Restrict columns to 120px max width:

```{python}
tbl_preview(
    sample_scores(15),
    max_col_width=120,
    min_tbl_width=400,
)
```

## Side-by-Side Comparison

Default Pandas output vs. `tbl_preview()` on the same data:

::: {layout-ncol=2}

```{python}
#| echo: false
import pandas as pd
df = pd.DataFrame(sample_scores(10))
df
```

```{python}
#| echo: false
tbl_preview(df)
```

:::
📄 07-text-heavy-tables.qmd
---
title: Text-Heavy Tables
---

## Long Strings (Default Width)

Cells with very long text are capped at `max_col_width` (250px
by default) and show an ellipsis instead of wrapping.

```{python}
from great_docs import tbl_preview

data = {
    "id": [1, 2, 3, 4, 5],
    "title": [
        "A short title",
        "A moderately long title that tests mid-range widths",
        "This title is intentionally very long so that it will definitely exceed the maximum column width and trigger text-overflow ellipsis behavior in the rendered table cell",
        "Brief",
        "Another extremely verbose title string that goes on and on to stress-test the truncation and overflow handling in the preview table renderer",
    ],
    "status": ["draft", "published", "review", "archived", "published"],
}

tbl_preview(data, show_all=True)
```

## Descriptions and Paragraphs

Real-world data often has paragraph-length text in columns.

```{python}
data = {
    "package": ["NumPy", "Pandas", "Polars", "Great Tables", "Pointblank"],
    "description": [
        "Fundamental package for scientific computing with Python. Provides N-dimensional arrays, linear algebra, Fourier transforms, and random number generation.",
        "Powerful data structures for data analysis, time series, and statistics. Built on NumPy with labeled axes, automatic alignment, and rich I/O.",
        "Lightning-fast DataFrame library in Rust with a Python API. Lazy evaluation, multi-threaded queries, and Apache Arrow memory format.",
        "Build beautiful, publication-quality tables in Python. Supports Polars and Pandas DataFrames with fine-grained styling, formatting, and export.",
        "Data validation library for Python. Define expectations, validate data, and generate detailed reports with table-level and column-level checks.",
    ],
    "version": ["1.26.0", "2.2.0", "0.20.0", "0.15.0", "0.14.0"],
}

tbl_preview(data, show_all=True)
```

## Narrow Max Width (120px)

Force aggressive truncation with a tight `max_col_width`:

```{python}
tbl_preview(data, show_all=True, max_col_width=120)
```

## Wide Max Width (500px)

Allow generous room — long text is still capped, but more is visible:

```{python}
tbl_preview(data, show_all=True, max_col_width=500)
```

## Mixed Short and Long Columns

Short numeric/code columns alongside verbose text — each column
gets its own computed width.

```{python}
data = {
    "code": ["E001", "E002", "E003", "W001", "W002", "I001", "I002", "E004"],
    "severity": ["error", "error", "error", "warning", "warning", "info", "info", "error"],
    "message": [
        "Undefined variable: foobar",
        "Type mismatch: expected int, got str in argument `count` of function process_batch()",
        "Division by zero in expression total / n_items where n_items evaluates to 0",
        "Unused import: os (imported but never referenced in module)",
        "Variable `tmp` assigned on line 42 but never used anywhere in the function body",
        "Module docstring missing: consider adding a module-level docstring",
        "Line too long: 127 characters (max 120). Consider breaking this into multiple lines for readability",
        "Syntax error: unexpected token ) at position 34 in expression parse(input))",
    ],
    "line": [12, 45, 78, 3, 42, 1, 99, 34],
}

tbl_preview(data, show_all=True)
```
📄 08-tsv-files.qmd
---
title: TSV Files
---

## Read a TSV File

`tbl_preview()` auto-detects `.tsv` and `.tab` files and reads
them with tab-delimited parsing.

```{python}
#| echo: false
import pathlib

tsv_path = pathlib.Path('assets/cities.tsv')
tsv_path.parent.mkdir(parents=True, exist_ok=True)
tsv_path.write_text(
    'city\tcountry\tpopulation\tarea_km2\n'
    'Tokyo\tJapan\t13960000\t2194\n'
    'Delhi\tIndia\t11030000\t1484\n'
    'Shanghai\tChina\t24870000\t6341\n'
    'São Paulo\tBrazil\t12330000\t1521\n'
    'Mexico City\tMexico\t9210000\t1485\n'
    'Cairo\tEgypt\t9540000\t3085\n'
    'Mumbai\tIndia\t12440000\t603\n'
    'Beijing\tChina\t21540000\t16411\n'
)
```

```{python}
from great_docs import tbl_preview

tbl_preview('assets/cities.tsv', show_all=True)
```

The badge shows **TSV** and the header reports the correct
row and column counts.
📄 09-jsonl-files.qmd
---
title: JSONL Files
---

## Read a JSONL File

Newline-delimited JSON (`.jsonl` / `.ndjson`) is a common
format for streaming data and log records.

```{python}
#| echo: false
import pathlib, json

records = [
    {'timestamp': '2025-01-15T08:30:00', 'level': 'INFO', 'module': 'auth', 'message': 'User login successful'},
    {'timestamp': '2025-01-15T08:31:12', 'level': 'WARNING', 'module': 'db', 'message': 'Slow query detected (3.2s)'},
    {'timestamp': '2025-01-15T08:32:45', 'level': 'ERROR', 'module': 'api', 'message': 'Request timeout on /v2/users'},
    {'timestamp': '2025-01-15T08:33:01', 'level': 'INFO', 'module': 'cache', 'message': 'Cache miss for key user:42'},
    {'timestamp': '2025-01-15T08:34:20', 'level': 'DEBUG', 'module': 'auth', 'message': 'Token refresh for session abc123'},
    {'timestamp': '2025-01-15T08:35:55', 'level': 'ERROR', 'module': 'db', 'message': 'Connection pool exhausted'},
    {'timestamp': '2025-01-15T08:36:10', 'level': 'INFO', 'module': 'api', 'message': 'Health check passed'},
    {'timestamp': '2025-01-15T08:37:30', 'level': 'WARNING', 'module': 'auth', 'message': 'Failed login attempt from 192.168.1.100'},
]

jsonl_path = pathlib.Path('assets/server_logs.jsonl')
jsonl_path.parent.mkdir(parents=True, exist_ok=True)
jsonl_path.write_text('\n'.join(json.dumps(r) for r in records) + '\n')
```

```{python}
from great_docs import tbl_preview

tbl_preview('assets/server_logs.jsonl', show_all=True)
```

## NDJSON Extension

The `.ndjson` extension is treated identically:

```{python}
#| echo: false
import shutil
shutil.copy('assets/server_logs.jsonl', 'assets/server_logs.ndjson')
```

```{python}
tbl_preview('assets/server_logs.ndjson', show_all=True)
```
📄 10-parquet-files.qmd
---
title: Parquet Files
---

## Read a Parquet File

Apache Parquet is a columnar storage format popular in data
engineering workflows.

```{python}
#| echo: false
import polars as pl, pathlib

df = pl.DataFrame({
    'product': ['Widget', 'Gadget', 'Gizmo', 'Doohickey', 'Thingamajig'],
    'category': ['Electronics', 'Tools', 'Kitchen', 'Garden', 'Office'],
    'price': [29.99, 49.50, 12.00, 8.75, 199.99],
    'in_stock': [True, False, True, True, False],
    'rating': [4.5, 3.8, 4.9, 4.2, 2.1],
})

pq_path = pathlib.Path('assets/products.parquet')
pq_path.parent.mkdir(parents=True, exist_ok=True)
df.write_parquet(str(pq_path))
```

```{python}
from great_docs import tbl_preview

tbl_preview('assets/products.parquet', show_all=True)
```

The badge shows **Parquet** and dtype labels are preserved
from the original Polars schema.
📄 11-feather-arrow-files.qmd
---
title: Feather & Arrow IPC Files
---

## Feather File

Feather (Apache Arrow IPC format) is fast for local analytics.

```{python}
#| echo: false
import polars as pl, pathlib

df = pl.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank'],
    'department': ['Engineering', 'Marketing', 'Engineering', 'Sales', 'Marketing', 'Sales'],
    'salary': [95000, 72000, 105000, 68000, 88000, 71000],
    'years': [5, 3, 8, 2, 6, 4],
})

feather_path = pathlib.Path('assets/employees.feather')
feather_path.parent.mkdir(parents=True, exist_ok=True)
df.write_ipc(str(feather_path))
```

```{python}
from great_docs import tbl_preview

tbl_preview('assets/employees.feather', show_all=True)
```

## Arrow IPC Extension

Files with `.arrow` or `.ipc` extensions are also read as
Arrow IPC, but get the **Arrow** badge instead of Feather:

```{python}
#| echo: false
import shutil
shutil.copy('assets/employees.feather', 'assets/employees.arrow')
```

```{python}
tbl_preview('assets/employees.arrow', show_all=True)
```
📄 12-arrow-tables.qmd
---
title: PyArrow Tables
---

## In-Memory Arrow Table

`tbl_preview()` also accepts a `pyarrow.Table` directly —
no file needed.

```{python}
import pyarrow as pa
from great_docs import tbl_preview

tbl = pa.table({
    'city': ['Tokyo', 'Delhi', 'Shanghai', 'São Paulo', 'Mexico City',
             'Cairo', 'Mumbai', 'Beijing', 'Dhaka', 'Osaka'],
    'country': ['Japan', 'India', 'China', 'Brazil', 'Mexico',
                'Egypt', 'India', 'China', 'Bangladesh', 'Japan'],
    'population_m': [13.96, 11.03, 24.87, 12.33, 9.21,
                     9.54, 12.44, 21.54, 8.91, 2.75],
    'area_km2': [2194, 1484, 6341, 1521, 1485,
                 3085, 603, 16411, 306, 225],
})

tbl_preview(tbl, show_all=True)
```

## Arrow Table with Typed Columns

PyArrow preserves rich type information — booleans, dates,
decimals — which `tbl_preview()` maps to short dtype labels.

```{python}
import pyarrow as pa
from datetime import date

tbl = pa.table({
    'event': ['Launch', 'Update', 'Hotfix', 'Deprecation'],
    'date': [date(2025, 1, 15), date(2025, 3, 1), date(2025, 3, 12), date(2025, 6, 30)],
    'critical': [True, False, True, False],
    'affected_users': [50000, 12000, 8500, 2000],
})

tbl_preview(tbl, show_all=True)
```
📄 README.md
# gdtest-tbl-preview

A showcase site demonstrating the `tbl_preview()` function from
Great Docs. Each user-guide page exercises a different combination
of data sources, table shapes, and display options.
📄 great-docs.yml
{}