From b62e21acb0292a0e3bb41a0c4d6e8b5f1dbcee8f Mon Sep 17 00:00:00 2001 From: Thomas Lin Pedersen Date: Thu, 19 Mar 2026 13:40:08 +0100 Subject: [PATCH 01/12] Fix #233 --- doc/syntax/index.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/syntax/index.qmd b/doc/syntax/index.qmd index 8b2f8837..004e7692 100644 --- a/doc/syntax/index.qmd +++ b/doc/syntax/index.qmd @@ -3,7 +3,7 @@ title: "Syntax" --- ## Main Clauses -ggsql augments the standard SQL syntax with a number of new clauses to describe a visualisation: +ggsql augments the standard SQL syntax with a number of new clauses to describe a visualisation. Apart from `VISUALISE` needing to be the first, the order of these clauses is arbitrary, though grouping e.g. all `DRAW` clauses will lead to queries that are easier to reason about: - [`VISUALISE`](clause/visualise.qmd) initiates the visualisation part of the query - [`DRAW`](clause/draw.qmd) adds a new layer to the visualisation From 2de981e8b4417b80cc6b9fa93778b2632123bf7d Mon Sep 17 00:00:00 2001 From: Thomas Lin Pedersen Date: Thu, 19 Mar 2026 13:43:51 +0100 Subject: [PATCH 02/12] Fix #236 --- doc/get_started.qmd | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/doc/get_started.qmd b/doc/get_started.qmd index 7cdd4618..a41a32f1 100644 --- a/doc/get_started.qmd +++ b/doc/get_started.qmd @@ -117,3 +117,24 @@ If you prefer to build from source or need the latest development version: ggsql-jupyter --install ``` +## The grammar of graphics +ggsql is a tool for visualising data, combining our 20 years of experience developing [ggplot2](https://ggplot2.tidyverse.org/) with a SQL-native syntax. +Unlike most visualisation systems, ggsql has an underlying grammar, based on the [Grammar of Graphics](https://en.wikipedia.org/wiki/Wilkinson%27s_Grammar_of_Graphics) by Leland Wilkinson. +This is a different approach than the one taken by most tools, which give you a set of pre-defined graphics, like scatterplots, bar charts, and pie charts. +ggsql instead gives you a number of independent components that you can combine to solve a very wide set of problems. + +This means there's a learning curve to ggsql: you have to learn a few big ideas about the grammar before you can be productive. +But we believe the payoff is worth it. +The grammar gives you new vocabulary and new ways to think about visualizations. +This allows you to create not only familiar graphics but also newer, better graphics. +You'll gain the ability to look at a visualization that someone else has made, analyse the key components, then recreate it yourself. +The hardest part of learning ggsql is likely to be unlearning the preconceptions that you bring over from previous visualization tools. + +We've tried to make the learning curve as easy as possible by keeping the grammar close to the SQL syntax that you're already familiar with. +You'll start with a classic `SELECT` statement to get the data that you want. +Then you'll use `VISUALIZE` (or `VISUALISE` ๐Ÿ‡ฌ๐Ÿ‡ง) to switch from creating a table of data to creating a plot of that data. +Then you'll `DRAW` a layer that maps columns in your data to aesthetics (visual properties), like position, colour, and shape. +Then you tweak the `SCALE`s, the mappings between the data and the visual properties, to make the plot easier to read. +Then you `FACET` the plot to show how the relationships differ across subsets of the data. +Finally you finish up by adding `LABEL`s to explain your plot to others. +This allows you to produce graphics using the same structured thinking that you already use to design a SQL query. From cbf5d276e96a6753225027951bfea3209cfe0676 Mon Sep 17 00:00:00 2001 From: Thomas Lin Pedersen Date: Thu, 19 Mar 2026 16:27:08 +0100 Subject: [PATCH 03/12] fix text linking --- doc/_quarto.yml | 95 +++++++------ doc/get_started.qmd | 140 ------------------- doc/get_started/_metadata.yml | 3 + doc/get_started/first_plot.qmd | 21 +++ doc/get_started/grammar.qmd | 24 ++++ doc/get_started/installation.qmd | 231 +++++++++++++++++++++++++++++++ doc/syntax/index.qmd | 2 +- doc/syntax/layer/type/text.qmd | 4 +- 8 files changed, 333 insertions(+), 187 deletions(-) delete mode 100644 doc/get_started.qmd create mode 100644 doc/get_started/_metadata.yml create mode 100644 doc/get_started/first_plot.qmd create mode 100644 doc/get_started/grammar.qmd create mode 100644 doc/get_started/installation.qmd diff --git a/doc/_quarto.yml b/doc/_quarto.yml index 5e464b54..5d030069 100644 --- a/doc/_quarto.yml +++ b/doc/_quarto.yml @@ -65,50 +65,57 @@ website: - text: Report a Bug href: https://github.com/ggsql-dev/ggsql/issues sidebar: - id: syntax - title: Syntax - style: "floating" - search: true - logo: false - contents: - - text: Overview - href: syntax/index.qmd - - section: "Main clauses" - contents: - - text: "`VISUALISE`" - href: syntax/clause/visualise.qmd - - text: "`DRAW`" - href: syntax/clause/draw.qmd - - text: "`PLACE`" - href: syntax/clause/place.qmd - - text: "`SCALE`" - href: syntax/clause/scale.qmd - - text: "`FACET`" - href: syntax/clause/facet.qmd - - text: "`PROJECT`" - href: syntax/clause/project.qmd - - text: "`LABEL`" - href: syntax/clause/label.qmd - - section: Layers - contents: - - section: Types - contents: - - auto: syntax/layer/type/* - - section: Position adjustment - contents: - - auto: syntax/layer/position/* - - section: Scales - contents: - - section: Types - contents: - - auto: syntax/scale/type/* - - section: Aesthetics - contents: - - auto: syntax/scale/aesthetic/* - - section: Coordinate systems - contents: - - auto: syntax/coord/* - + - id: syntax + title: Syntax + style: "floating" + search: true + logo: false + contents: + - text: Overview + href: syntax/index.qmd + - section: "Main clauses" + contents: + - text: "`VISUALISE`" + href: syntax/clause/visualise.qmd + - text: "`DRAW`" + href: syntax/clause/draw.qmd + - text: "`PLACE`" + href: syntax/clause/place.qmd + - text: "`SCALE`" + href: syntax/clause/scale.qmd + - text: "`FACET`" + href: syntax/clause/facet.qmd + - text: "`PROJECT`" + href: syntax/clause/project.qmd + - text: "`LABEL`" + href: syntax/clause/label.qmd + - section: Layers + contents: + - section: Types + contents: + - auto: syntax/layer/type/* + - section: Position adjustment + contents: + - auto: syntax/layer/position/* + - section: Scales + contents: + - section: Types + contents: + - auto: syntax/scale/type/* + - section: Aesthetics + contents: + - auto: syntax/scale/aesthetic/* + - section: Coordinate systems + contents: + - auto: syntax/coord/* + - id: get_started + title: Get started + style: "floating" + search: false + logo: false + contents: + - text: Installation + href: get_started/installation.qmd format: html: diff --git a/doc/get_started.qmd b/doc/get_started.qmd deleted file mode 100644 index a41a32f1..00000000 --- a/doc/get_started.qmd +++ /dev/null @@ -1,140 +0,0 @@ ---- -title: "Getting started" ---- - - - -Before you spend time on the minutia of installing ggsql โ€” not that it is particularly daunting โ€” why not try it out right now, right here, in your browser? - -The code below shows a simple ggsql example. But it is not just a static piece of text and an image. It is ggsql running right in your browser, using one of the built-in datasets. Try to change e.g. the title and see the plot update as you type. Even though this may be your first encounter with the ggsql syntax you might already get a sense of how some of the things fit together. See if you can change the code to instead show the different species as different shapes - -```{ggsql} -VISUALISE bill_len AS x, bill_dep AS y, species AS fill FROM ggsql:penguins -DRAW point -SCALE x RENAMING * => '{} mm' -LABEL - title => 'Relationship between bill dimensions in 3 species of penguins', - x => 'Bill length', - y => 'Bill depth' -``` - -Congratulations! You have started your journey with ggsql! All examples you see on this site will be interactive. Please experiment to your heart's content. If you want a more dedicated exploration experience head to [our playground](wasm/) which provides a simple IDE with a number of examples to try out. - -Now that you have gotten a feel for ggsql you may want to try running locally with your own data. Read on to learn how. - -## Installation - -### Building from Source - -If you prefer to build from source or need the latest development version: - -1. **Clone the repository:** - - ```bash - git clone https://github.com/posit-dev/ggsql - cd ggsql - ``` - -2. **Install tree-sitter CLI:** - - ```bash - npm install -g tree-sitter-cli - ``` - -3. **Build the project:** - - ```bash - cd tree-sitter-ggsql && tree-sitter generate && cd .. - cargo build --release - ``` - -4. **Install the CLI:** - ```bash - cargo install --path src - ``` - -5. **Install the Jupyter kernel (optional):** - ```bash - cargo install --path ggsql-jupyter - ggsql-jupyter --install - ``` - -## The grammar of graphics -ggsql is a tool for visualising data, combining our 20 years of experience developing [ggplot2](https://ggplot2.tidyverse.org/) with a SQL-native syntax. -Unlike most visualisation systems, ggsql has an underlying grammar, based on the [Grammar of Graphics](https://en.wikipedia.org/wiki/Wilkinson%27s_Grammar_of_Graphics) by Leland Wilkinson. -This is a different approach than the one taken by most tools, which give you a set of pre-defined graphics, like scatterplots, bar charts, and pie charts. -ggsql instead gives you a number of independent components that you can combine to solve a very wide set of problems. - -This means there's a learning curve to ggsql: you have to learn a few big ideas about the grammar before you can be productive. -But we believe the payoff is worth it. -The grammar gives you new vocabulary and new ways to think about visualizations. -This allows you to create not only familiar graphics but also newer, better graphics. -You'll gain the ability to look at a visualization that someone else has made, analyse the key components, then recreate it yourself. -The hardest part of learning ggsql is likely to be unlearning the preconceptions that you bring over from previous visualization tools. - -We've tried to make the learning curve as easy as possible by keeping the grammar close to the SQL syntax that you're already familiar with. -You'll start with a classic `SELECT` statement to get the data that you want. -Then you'll use `VISUALIZE` (or `VISUALISE` ๐Ÿ‡ฌ๐Ÿ‡ง) to switch from creating a table of data to creating a plot of that data. -Then you'll `DRAW` a layer that maps columns in your data to aesthetics (visual properties), like position, colour, and shape. -Then you tweak the `SCALE`s, the mappings between the data and the visual properties, to make the plot easier to read. -Then you `FACET` the plot to show how the relationships differ across subsets of the data. -Finally you finish up by adding `LABEL`s to explain your plot to others. -This allows you to produce graphics using the same structured thinking that you already use to design a SQL query. diff --git a/doc/get_started/_metadata.yml b/doc/get_started/_metadata.yml new file mode 100644 index 00000000..23268da8 --- /dev/null +++ b/doc/get_started/_metadata.yml @@ -0,0 +1,3 @@ +sidebar: get_started +page-navigation: false +toc: false diff --git a/doc/get_started/first_plot.qmd b/doc/get_started/first_plot.qmd new file mode 100644 index 00000000..d5750103 --- /dev/null +++ b/doc/get_started/first_plot.qmd @@ -0,0 +1,21 @@ +--- +title: "Your first plot" +--- + +Before you spend time on the minutia of installing ggsql โ€” not that it is particularly daunting โ€” why not try it out right now, right here, in your browser? + +The code below shows a simple ggsql example. But it is not just a static piece of text and an image. It is ggsql running right in your browser, using one of the built-in datasets. Try to change e.g. the title and see the plot update as you type. Even though this may be your first encounter with the ggsql syntax you might already get a sense of how some of the things fit together. See if you can change the code to instead show the different species as different shapes + +```{ggsql} +VISUALISE bill_len AS x, bill_dep AS y, species AS fill FROM ggsql:penguins +DRAW point +SCALE x RENAMING * => '{} mm' +LABEL + title => 'Relationship between bill dimensions in 3 species of penguins', + x => 'Bill length', + y => 'Bill depth' +``` + +Congratulations! You have started your journey with ggsql! All examples you see on this site will be interactive. Please experiment to your heart's content. If you want a more dedicated exploration experience head to [our playground](wasm/) which provides a simple IDE with a number of examples to try out. + +Now that you have gotten a feel for ggsql you may want to try running locally with your own data. Read on to learn how. diff --git a/doc/get_started/grammar.qmd b/doc/get_started/grammar.qmd new file mode 100644 index 00000000..bc1bf860 --- /dev/null +++ b/doc/get_started/grammar.qmd @@ -0,0 +1,24 @@ +--- +title: The grammar of graphics +--- + +ggsql is a tool for visualising data, combining our 20 years of experience developing [ggplot2](https://ggplot2.tidyverse.org/) with a SQL-native syntax. +Unlike most visualisation systems, ggsql has an underlying grammar, based on the [Grammar of Graphics](https://en.wikipedia.org/wiki/Wilkinson%27s_Grammar_of_Graphics) by Leland Wilkinson. +This is a different approach than the one taken by most tools, which give you a set of pre-defined graphics, like scatterplots, bar charts, and pie charts. +ggsql instead gives you a number of independent components that you can combine to solve a very wide set of problems. + +This means there's a learning curve to ggsql: you have to learn a few big ideas about the grammar before you can be productive. +But we believe the payoff is worth it. +The grammar gives you new vocabulary and new ways to think about visualizations. +This allows you to create not only familiar graphics but also newer, better graphics. +You'll gain the ability to look at a visualization that someone else has made, analyse the key components, then recreate it yourself. +The hardest part of learning ggsql is likely to be unlearning the preconceptions that you bring over from previous visualization tools. + +We've tried to make the learning curve as easy as possible by keeping the grammar close to the SQL syntax that you're already familiar with. +You'll start with a classic `SELECT` statement to get the data that you want. +Then you'll use `VISUALIZE` (or `VISUALISE` ๐Ÿ‡ฌ๐Ÿ‡ง) to switch from creating a table of data to creating a plot of that data. +Then you'll `DRAW` a layer that maps columns in your data to aesthetics (visual properties), like position, colour, and shape. +Then you tweak the `SCALE`s, the mappings between the data and the visual properties, to make the plot easier to read. +Then you `FACET` the plot to show how the relationships differ across subsets of the data. +Finally you finish up by adding `LABEL`s to explain your plot to others. +This allows you to produce graphics using the same structured thinking that you already use to design a SQL query. diff --git a/doc/get_started/installation.qmd b/doc/get_started/installation.qmd new file mode 100644 index 00000000..e5c49ba0 --- /dev/null +++ b/doc/get_started/installation.qmd @@ -0,0 +1,231 @@ +--- +title: "Installation" +--- + +While all of the examples on this website uses the ggsql web assembly build to let you run it in the browser, you likely want it on your own computer, interfacing with your local data. + +ggsql provides native installers for Windows, macOS, and Linux. Choose the best option for your platform below. + +::: {#installer-recommended} + +::: + +### All platforms + +::: {#installer-table} + +::: + +```{=html} + + + +``` + +### Command line installation + +If you prefer installing via the command line: + +```bash +cargo install ggsql +``` diff --git a/doc/syntax/index.qmd b/doc/syntax/index.qmd index 004e7692..2827aa49 100644 --- a/doc/syntax/index.qmd +++ b/doc/syntax/index.qmd @@ -26,7 +26,7 @@ There are many different layers to choose from when visualising your data. Some - [`area`](layer/type/area.qmd) is used to display series as an area chart. - [`ribbon`](layer/type/ribbon.qmd) is used to display series extrema. - [`polygon`](layer/type/polygon.qmd) is used to display arbitrary shapes as polygons. -- [`text`](layer/text.qmd) is used to render datapoints as text. +- [`text`](layer/type/text.qmd) is used to render datapoints as text. - [`bar`](layer/type/bar.qmd) creates a bar chart, optionally calculating y from the number of records in each bar. - [`density`](layer/type/density.qmd) creates univariate kernel density estimates, showing the distribution of a variable. - [`violin`](layer/type/violin.qmd) displays a rotated kernel density estimate. diff --git a/doc/syntax/layer/type/text.qmd b/doc/syntax/layer/type/text.qmd index 0e601c5b..b3818531 100644 --- a/doc/syntax/layer/type/text.qmd +++ b/doc/syntax/layer/type/text.qmd @@ -2,7 +2,7 @@ title: "Text" --- -> Layers are declared with the [`DRAW` clause](../clause/draw.qmd). Read the documentation for this clause for a thorough description of how to use it. +> Layers are declared with the [`DRAW` clause](../../clause/draw.qmd). Read the documentation for this clause for a thorough description of how to use it. The text layer displays rows in the data as text. It can be used as a visualisation itself, or used to annotate a different layer. @@ -146,4 +146,4 @@ VISUALISE bill_len AS x, bill_dep AS y FROM ggsql:penguins label => ['Adelie', 'Chinstrap', 'Gentoo'], x => [40, 50, 50], y => [19, 19, 15] -``` \ No newline at end of file +``` From b2bcead4b9328dd2aa05b406f27cdf96b439d7ca Mon Sep 17 00:00:00 2001 From: Thomas Lin Pedersen Date: Fri, 20 Mar 2026 09:49:37 +0100 Subject: [PATCH 04/12] updates to get started --- doc/_quarto.yml | 7 +- doc/examples.qmd | 781 ------------------------------- doc/get_started/_metadata.yml | 2 +- doc/get_started/first_plot.qmd | 4 +- doc/get_started/installation.qmd | 59 ++- 5 files changed, 64 insertions(+), 789 deletions(-) delete mode 100644 doc/examples.qmd diff --git a/doc/_quarto.yml b/doc/_quarto.yml index 5d030069..1cbfd29c 100644 --- a/doc/_quarto.yml +++ b/doc/_quarto.yml @@ -30,7 +30,8 @@ website: keyboard-shortcut: [] navbar: left: - - get_started.qmd + - text: Get started + href: get_started/installation.qmd - text: Syntax menu: - text: Overview @@ -116,6 +117,10 @@ website: contents: - text: Installation href: get_started/installation.qmd + - text: The first plot + href: get_started/first_plot.qmd + - text: Grammar of graphics + href: get_started/grammar.qmd format: html: diff --git a/doc/examples.qmd b/doc/examples.qmd deleted file mode 100644 index 1c1d3ffb..00000000 --- a/doc/examples.qmd +++ /dev/null @@ -1,781 +0,0 @@ ---- -title: Examples ---- - -This document demonstrates various ggsql features with runnable examples using CSV files. - -```{ggsql} -#| echo: false -#| output: false -COPY ( - SELECT * FROM (VALUES - (5.2, 18.5), - (8.7, 22.3), - (12.3, 28.9), - (15.8, 35.2), - (19.4, 42.7), - (23.1, 38.6), - (26.8, 45.1), - (30.2, 52.8), - (33.9, 48.3), - (37.5, 55.9), - (41.2, 62.4), - (44.8, 58.7), - (48.3, 65.2), - (52.1, 71.8), - (55.7, 68.1), - (59.4, 74.6) - ) AS t(x, y) -) TO 'data.csv' (HEADER, DELIMITER ',') -``` - -```{ggsql} -#| echo: false -#| output: false -COPY ( - SELECT * FROM (VALUES - ('2023-01-15'::DATE, 1000.0, 'North', 'Electronics', 5), - ('2023-02-10'::DATE, 1200.0, 'South', 'Electronics', 8), - ('2023-03-05'::DATE, 1400.0, 'East', 'Electronics', 7), - ('2023-04-20'::DATE, 1100.0, 'West', 'Electronics', 6), - ('2023-05-12'::DATE, 1600.0, 'North', 'Electronics', 9), - ('2023-06-08'::DATE, 1800.0, 'South', 'Electronics', 10), - ('2023-07-14'::DATE, 2000.0, 'East', 'Electronics', 11), - ('2023-08-22'::DATE, 2200.0, 'West', 'Electronics', 12), - ('2023-09-18'::DATE, 1900.0, 'North', 'Electronics', 8), - ('2023-10-25'::DATE, 2400.0, 'South', 'Electronics', 14), - ('2023-11-11'::DATE, 2600.0, 'East', 'Electronics', 15), - ('2023-12-05'::DATE, 3000.0, 'West', 'Electronics', 16), - ('2023-01-20'::DATE, 800.0, 'North', 'Clothing', 25), - ('2023-02-15'::DATE, 900.0, 'South', 'Clothing', 30), - ('2023-03-10'::DATE, 1100.0, 'East', 'Clothing', 35), - ('2023-04-25'::DATE, 1300.0, 'West', 'Clothing', 38), - ('2023-05-18'::DATE, 1500.0, 'North', 'Clothing', 42), - ('2023-06-12'::DATE, 1700.0, 'South', 'Clothing', 45), - ('2023-07-20'::DATE, 1900.0, 'East', 'Clothing', 48), - ('2023-08-28'::DATE, 2100.0, 'West', 'Clothing', 50), - ('2023-09-22'::DATE, 2300.0, 'North', 'Clothing', 52), - ('2023-10-30'::DATE, 2500.0, 'South', 'Clothing', 55), - ('2023-11-15'::DATE, 2700.0, 'East', 'Clothing', 58), - ('2023-12-10'::DATE, 2900.0, 'West', 'Clothing', 60), - ('2023-01-25'::DATE, 600.0, 'North', 'Furniture', 3), - ('2023-02-18'::DATE, 700.0, 'South', 'Furniture', 3), - ('2023-03-15'::DATE, 850.0, 'East', 'Furniture', 4), - ('2023-04-28'::DATE, 950.0, 'West', 'Furniture', 4), - ('2023-05-22'::DATE, 1050.0, 'North', 'Furniture', 5), - ('2023-06-16'::DATE, 1150.0, 'South', 'Furniture', 5), - ('2023-07-24'::DATE, 1250.0, 'East', 'Furniture', 5), - ('2023-08-30'::DATE, 1350.0, 'West', 'Furniture', 6), - ('2023-09-26'::DATE, 1450.0, 'North', 'Furniture', 6), - ('2023-10-31'::DATE, 1550.0, 'South', 'Furniture', 6), - ('2023-11-20'::DATE, 1650.0, 'East', 'Furniture', 7), - ('2023-12-15'::DATE, 1750.0, 'West', 'Furniture', 7) - ) AS t(sale_date, revenue, region, category, quantity) -) TO 'sales.csv' (HEADER, DELIMITER ',') -``` - -```{ggsql} -#| echo: false -#| output: false -COPY ( - SELECT * FROM (VALUES - ('2023-01-01'::DATE, 100.0), - ('2023-01-08'::DATE, 110.0), - ('2023-01-15'::DATE, 105.0), - ('2023-01-22'::DATE, 115.0), - ('2023-01-29'::DATE, 120.0), - ('2023-02-05'::DATE, 118.0), - ('2023-02-12'::DATE, 125.0), - ('2023-02-19'::DATE, 130.0), - ('2023-02-26'::DATE, 128.0), - ('2023-03-05'::DATE, 135.0), - ('2023-03-12'::DATE, 142.0), - ('2023-03-19'::DATE, 138.0), - ('2023-03-26'::DATE, 145.0), - ('2023-04-02'::DATE, 150.0), - ('2023-04-09'::DATE, 148.0), - ('2023-04-16'::DATE, 155.0), - ('2023-04-23'::DATE, 160.0), - ('2023-04-30'::DATE, 158.0), - ('2023-05-07'::DATE, 165.0), - ('2023-05-14'::DATE, 170.0) - ) AS t(date, value) -) TO 'timeseries.csv' (HEADER, DELIMITER ',') -``` - -```{ggsql} -#| echo: false -#| output: false -COPY ( - SELECT * FROM (VALUES - ('2023-01-01'::DATE, 45.2, 'Sales'), - ('2023-02-01'::DATE, 52.1, 'Sales'), - ('2023-03-01'::DATE, 48.7, 'Sales'), - ('2023-04-01'::DATE, 58.3, 'Sales'), - ('2023-05-01'::DATE, 62.5, 'Sales'), - ('2023-06-01'::DATE, 67.8, 'Sales'), - ('2023-07-01'::DATE, 71.2, 'Sales'), - ('2023-08-01'::DATE, 75.6, 'Sales'), - ('2023-09-01'::DATE, 80.1, 'Sales'), - ('2023-10-01'::DATE, 85.4, 'Sales'), - ('2023-11-01'::DATE, 90.2, 'Sales'), - ('2023-12-01'::DATE, 95.8, 'Sales'), - ('2023-01-01'::DATE, 120.5, 'Marketing'), - ('2023-02-01'::DATE, 135.2, 'Marketing'), - ('2023-03-01'::DATE, 128.9, 'Marketing'), - ('2023-04-01'::DATE, 142.3, 'Marketing'), - ('2023-05-01'::DATE, 155.7, 'Marketing'), - ('2023-06-01'::DATE, 148.2, 'Marketing'), - ('2023-07-01'::DATE, 162.8, 'Marketing'), - ('2023-08-01'::DATE, 175.4, 'Marketing'), - ('2023-09-01'::DATE, 168.9, 'Marketing'), - ('2023-10-01'::DATE, 182.5, 'Marketing'), - ('2023-11-01'::DATE, 195.1, 'Marketing'), - ('2023-12-01'::DATE, 188.7, 'Marketing'), - ('2023-01-01'::DATE, 78.3, 'Support'), - ('2023-02-01'::DATE, 82.1, 'Support'), - ('2023-03-01'::DATE, 75.6, 'Support'), - ('2023-04-01'::DATE, 85.9, 'Support'), - ('2023-05-01'::DATE, 92.4, 'Support'), - ('2023-06-01'::DATE, 88.7, 'Support'), - ('2023-07-01'::DATE, 95.2, 'Support'), - ('2023-08-01'::DATE, 101.8, 'Support'), - ('2023-09-01'::DATE, 97.5, 'Support'), - ('2023-10-01'::DATE, 105.3, 'Support'), - ('2023-11-01'::DATE, 112.6, 'Support'), - ('2023-12-01'::DATE, 108.9, 'Support') - ) AS t(date, value, category) -) TO 'metrics.csv' (HEADER, DELIMITER ',') -``` - -## Basic Visualizations - -### Simple Scatter Plot - -```{ggsql} -SELECT x, y FROM 'data.csv' -VISUALISE x, y -DRAW point -``` - -```{ggsql} -VISUALISE bill_len AS x, bill_dep AS y, species AS color FROM ggsql:penguins -DRAW point -``` - -### Line Chart with Date Scale - -```{ggsql} -SELECT sale_date, revenue FROM 'sales.csv' -WHERE category = 'Electronics' -VISUALISE sale_date AS x, revenue AS y -DRAW line -SCALE x VIA date -LABEL - title => 'Electronics Revenue Over Time', - x => 'Date', - y => 'Revenue ($)' -``` - -```{ggsql} -SELECT * FROM ggsql:airquality -VISUALISE Date AS x -DRAW line MAPPING Ozone AS y, 'Ozone' AS color -DRAW line MAPPING Temp AS y, 'Temp' AS color -``` - -### Bar Chart by Category - -```{ggsql} -SELECT category, SUM(revenue) as total -FROM 'sales.csv' -GROUP BY category -VISUALISE category AS x, total AS y, category AS fill -DRAW bar -LABEL - title => 'Total Revenue by Category', - x => 'Category', - y => 'Total Revenue ($)' -``` - -### Line chart with multiple lines with same aesthetics - -```{ggsql} -SELECT * FROM 'sales.csv' -VISUALISE sale_date AS x, revenue AS y -DRAW line - PARTITION BY category -``` - -## Statistical Transformations - -Statistical transformations automatically compute aggregations for certain geom types. - -### Histogram - -When using `DRAW histogram`, ggsql automatically bins continuous data and counts occurrences. You only need to specify the x aesthetic: - -```{ggsql} -SELECT revenue FROM 'sales.csv' -VISUALISE revenue AS x -DRAW histogram -LABEL - title => 'Revenue Distribution', - x => 'Revenue ($)', - y => 'Count' -``` - -### Bar with Automatic Count - -When using `DRAW bar` without a y aesthetic, ggsql automatically counts occurrences of each x value: - -```{ggsql} -SELECT category FROM 'sales.csv' -VISUALISE category AS x -DRAW bar -LABEL - title => 'Sales Count by Category', - x => 'Category', - y => 'Count' -``` - -### Bar with Weighted Count - -You can also specify a weight aesthetic to sum values instead of counting: - -```{ggsql} -SELECT category, revenue FROM 'sales.csv' -VISUALISE category AS x, revenue AS weight -DRAW bar -LABEL - title => 'Total Revenue by Category', - x => 'Category', - y => 'Revenue ($)' -``` - -### Histogram Settings - -Control histogram binning with `SETTING` options: - -**Custom number of bins:** - -```{ggsql} -SELECT revenue FROM 'sales.csv' -VISUALISE revenue AS x -DRAW histogram - SETTING bins => 10 -LABEL - title => 'Revenue Distribution (10 bins)', - x => 'Revenue ($)', - y => 'Count' -``` - -**Explicit bin width** (overrides bins): - -```{ggsql} -SELECT revenue FROM 'sales.csv' -VISUALISE revenue AS x -DRAW histogram - SETTING binwidth => 500 -LABEL - title => 'Revenue Distribution (500 bin width)', - x => 'Revenue ($)', - y => 'Count' -``` - -**Left-closed intervals** (default is right-closed `(a, b]`): - -```{ggsql} -SELECT revenue FROM 'sales.csv' -VISUALISE revenue AS x -DRAW histogram - SETTING bins => 8, closed => 'left' -LABEL - title => 'Revenue Distribution (left-closed intervals)', - x => 'Revenue ($)', - y => 'Count' -``` - -### Histogram Remapping - -Histogram computes several statistics: `bin`, `bin_end`, `count`, and `density`. By default, `count` is mapped to `y`. Use `REMAPPING` to show density (proportion) instead: - -```{ggsql} -SELECT revenue FROM 'sales.csv' -VISUALISE revenue AS x -DRAW histogram - REMAPPING density AS y -LABEL - title => 'Revenue Density Distribution', - x => 'Revenue ($)', - y => 'Density' -``` - -### Bar Width Setting - -Control bar width with the `width` setting (0-1 scale, default 0.9): - -```{ggsql} -SELECT category FROM 'sales.csv' -VISUALISE category AS x -DRAW bar - SETTING width => 0.5 -LABEL - title => 'Sales Count (Narrow Bars)', - x => 'Category', - y => 'Count' -``` - -### Bar Remapping - -Bar computes `count` and `proportion` statistics. By default, `count` is mapped to `y`. Use `REMAPPING` to show proportions instead: - -```{ggsql} -SELECT category FROM 'sales.csv' -VISUALISE category AS x -DRAW bar - REMAPPING proportion AS y -LABEL - title => 'Sales Proportion by Category', - x => 'Category', - y => 'Proportion' -``` - -Combine with `weight` to show weighted proportions: - -```{ggsql} -SELECT category, revenue FROM 'sales.csv' -VISUALISE category AS x, revenue AS weight -DRAW bar - REMAPPING proportion AS y -LABEL - title => 'Revenue Share by Category', - x => 'Category', - y => 'Share of Total Revenue' -``` - -## Multiple Layers - -### Line with Points - -```{ggsql} -SELECT date, value FROM 'timeseries.csv' -VISUALISE date AS x, value AS y -DRAW line - SETTING color => 'blue' -DRAW point - SETTING size => 6, color => 'red' -SCALE x VIA date -LABEL - title => 'Time Series with Points', - x => 'Date', - y => 'Value' -``` - -### Colored Lines by Category - -```{ggsql} -SELECT date, value, category FROM 'metrics.csv' -VISUALISE date AS x, value AS y, category AS color -DRAW line -SCALE x VIA date -LABEL - title => 'Metrics by Category', - x => 'Date', - y => 'Value' -``` - -## Faceting - -### Facet by Region - -```{ggsql} -SELECT sale_date, revenue, region FROM 'sales.csv' -WHERE category = 'Electronics' -VISUALISE sale_date AS x, revenue AS y -DRAW line -SCALE x VIA date -FACET region -LABEL - title => 'Electronics Sales by Region', - x => 'Date', - y => 'Revenue ($)' -``` - -### Facet Grid - -```{ggsql} -SELECT - DATE_TRUNC('month', sale_date) as month, - region, - category, - SUM(revenue) as total_revenue, - SUM(quantity) * 100 as total_quantity_scaled -FROM 'sales.csv' -GROUP BY DATE_TRUNC('month', sale_date), region, category -VISUALISE month AS x -DRAW line - MAPPING total_revenue AS y - SETTING color => 'steelblue' -DRAW point - MAPPING total_revenue AS y - SETTING size => 6, color => 'darkblue' -DRAW line - MAPPING total_quantity_scaled AS y - SETTING color => 'coral' -DRAW point - MAPPING total_quantity_scaled AS y - SETTING size => 6, color => 'orangered' -SCALE x VIA date -FACET region BY category -LABEL - title => 'Monthly Revenue and Quantity by Region and Category', - x => 'Month', - y => 'Value' -``` - -## Projections - -### Pie Chart with Polar Coordinates - -```{ggsql} -SELECT category, SUM(revenue) as total -FROM 'sales.csv' -GROUP BY category -VISUALISE total AS y, category AS fill -DRAW bar -PROJECT y, x TO polar -LABEL - title => 'Revenue Distribution by Category' -``` - -## Constant Mappings - -Constants can be used in both the VISUALISE clause (global) and MAPPING clauses (per-layer) to set fixed aesthetic values. - -### Different Constants Per Layer - -Each layer can have its own constant value, creating a legend showing all values: - -```{ggsql} -WITH monthly AS ( - SELECT - DATE_TRUNC('month', sale_date) as month, - category, - SUM(revenue) as revenue - FROM 'sales.csv' - GROUP BY DATE_TRUNC('month', sale_date), category -) -VISUALISE month AS x, revenue AS y -DRAW line - MAPPING 'Electronics' AS color FROM monthly - FILTER category = 'Electronics' -DRAW line - MAPPING 'Clothing' AS color FROM monthly - FILTER category = 'Clothing' -DRAW line - MAPPING 'Furniture' AS color FROM monthly - FILTER category = 'Furniture' -SCALE x VIA date -LABEL - title => 'Revenue by Category (Constant Colors)', - x => 'Month', - y => 'Revenue ($)' -``` - -### Mixed Constants and Columns - -When mixing constant and column mappings for the same aesthetic, the axis/legend label uses the first non-constant column name: - -```{ggsql} -SELECT date, value, category FROM 'metrics.csv' -VISUALISE date AS x -DRAW line - MAPPING value AS y, category AS color -DRAW point - MAPPING 120 AS y - SETTING size => 3, color => 'blue' -SCALE x VIA date -LABEL - title => 'Metrics with Threshold Line', - x => 'Date' -``` - -### Numeric Constants - -Numbers work as constants too: - -```{ggsql} -SELECT x, y FROM 'data.csv' -VISUALISE x, y -DRAW point - SETTING color => 'blue', size => 10 -DRAW point - SETTING color => 'red', size => 5 - FILTER y > 50 -LABEL - title => 'Scatter Plot with Constant Sizes' -``` - -## Layer filtering - -### Filter one layer - -```{ggsql} -SELECT date, value FROM 'timeseries.csv' -VISUALISE date AS x, value AS y -DRAW line - SETTING color => 'blue' -DRAW point - SETTING color => 'red', size => 6 - FILTER value < 130 -SCALE x VIA date -LABEL - title => 'Time Series with Points', - x => 'Date', - y => 'Value' -``` - -## Layer ordering - -### ORDER BY in a layer - -Use `ORDER BY` to ensure data is sorted correctly within a layer. This is especially important for line charts where the order of points affects the visual path: - -```{ggsql} -WITH unordered_data AS ( - SELECT * FROM (VALUES - (150.0, '2023-03-01'::DATE), - (100.0, '2023-01-01'::DATE), - (120.0, '2023-05-01'::DATE), - (200.0, '2023-02-01'::DATE), - (180.0, '2023-04-01'::DATE) - ) AS t(value, date) -) -VISUALISE -DRAW path - MAPPING date AS x, value AS y FROM unordered_data - ORDER BY date -DRAW point - MAPPING date AS x, value AS y FROM unordered_data - SETTING size => 6, color => 'red' -SCALE x VIA date -LABEL - title => 'Line Chart with ORDER BY', - x => 'Date', - y => 'Value' -``` - -### Combining FILTER and ORDER BY - -The `ORDER BY` clause can be combined with `FILTER` and other layer options: - -```{ggsql} -SELECT date, value, category FROM 'metrics.csv' -VISUALISE -DRAW path - MAPPING date AS x, value AS y, category AS color - FILTER category != 'Support' - ORDER BY value -DRAW point - MAPPING date AS x, value AS y, category AS color - SETTING size => 3 - FILTER category != 'Support' -SCALE x VIA date -LABEL - title => 'Sales and Marketing Metrics (Ordered)', - x => 'Date', - y => 'Value' -``` - -## Common Table Expressions (CTEs) - -### Simple CTE with VISUALISE FROM - -```{ggsql} -WITH monthly_sales AS ( - SELECT - DATE_TRUNC('month', sale_date) as month, - SUM(revenue) as total_revenue - FROM 'sales.csv' - GROUP BY DATE_TRUNC('month', sale_date) -) -VISUALISE month AS x, total_revenue AS y FROM monthly_sales -DRAW line -DRAW point -SCALE x VIA date -LABEL - title => 'Monthly Revenue Trends', - x => 'Month', - y => 'Revenue ($)' -``` - -### Multiple CTEs - -```{ggsql} -WITH daily_sales AS ( - SELECT sale_date, region, SUM(revenue) as revenue - FROM 'sales.csv' - GROUP BY sale_date, region -), -regional_totals AS ( - SELECT region, SUM(revenue) as total - FROM daily_sales - GROUP BY region -) -VISUALISE region AS x, total AS y, region AS fill FROM regional_totals -DRAW bar -PROJECT y, x TO cartesian -LABEL - title => 'Total Revenue by Region', - x => 'Region', - y => 'Total Revenue ($)' -``` - -## Layer-Specific Data Sources (MAPPING FROM) - -Layers can pull data from different sources using `MAPPING FROM`. This enables overlaying data from different CTEs or tables. - -### Comparing Actuals vs Targets - -Each layer can reference a different CTE using `MAPPING ... FROM cte_name`: - -```{ggsql} -WITH actuals AS ( - SELECT - DATE_TRUNC('month', sale_date) as month, - SUM(revenue) as value - FROM 'sales.csv' - GROUP BY DATE_TRUNC('month', sale_date) -), -targets AS ( - SELECT * FROM (VALUES - ('2023-01-01'::DATE, 5000.0), - ('2023-02-01'::DATE, 5500.0), - ('2023-03-01'::DATE, 6000.0), - ('2023-04-01'::DATE, 6500.0), - ('2023-05-01'::DATE, 7000.0), - ('2023-06-01'::DATE, 7500.0), - ('2023-07-01'::DATE, 8000.0), - ('2023-08-01'::DATE, 8500.0), - ('2023-09-01'::DATE, 9000.0), - ('2023-10-01'::DATE, 9500.0), - ('2023-11-01'::DATE, 10000.0), - ('2023-12-01'::DATE, 10500.0) - ) AS t(month, value) -) -VISUALISE -DRAW line - MAPPING month AS x, value AS y, 'Actual' AS color FROM actuals -DRAW point - MAPPING month AS x, value AS y, 'Actual' AS color FROM actuals - SETTING size => 6 -DRAW line - MAPPING month AS x, value AS y, 'Target' AS color FROM targets -SCALE x VIA date -LABEL - title => 'Revenue: Actual vs Target', - x => 'Month', - y => 'Revenue ($)' -``` - -### CTE Chain: Raw โ†’ Filtered โ†’ Aggregated - -CTEs can reference other CTEs, creating a data transformation pipeline: - -```{ggsql} -WITH raw_data AS ( - SELECT sale_date, revenue, category, region - FROM 'sales.csv' -), -electronics_only AS ( - SELECT * FROM raw_data - WHERE category = 'Electronics' -), -monthly_electronics AS ( - SELECT - DATE_TRUNC('month', sale_date) as month, - region, - SUM(revenue) as total - FROM electronics_only - GROUP BY DATE_TRUNC('month', sale_date), region -) -VISUALISE month AS x, total AS y, region AS color FROM monthly_electronics -DRAW line -DRAW point -SCALE x VIA date -LABEL - title => 'Electronics Revenue by Region (CTE Chain)', - x => 'Month', - y => 'Revenue ($)' -``` - -### Layer FROM with FILTER - -Combine `FROM` with `FILTER` to get filtered subsets from a CTE: - -```{ggsql} -WITH all_sales AS ( - SELECT - DATE_TRUNC('month', sale_date) as month, - category, - SUM(revenue) as revenue - FROM 'sales.csv' - GROUP BY DATE_TRUNC('month', sale_date), category -) -VISUALISE -DRAW line - MAPPING month AS x, revenue AS y, 'All Categories' AS color FROM all_sales -DRAW line - MAPPING month AS x, revenue AS y, 'Electronics' AS color FROM all_sales - FILTER category = 'Electronics' -DRAW line - MAPPING month AS x, revenue AS y, 'Clothing' AS color FROM all_sales - FILTER category = 'Clothing' -SCALE x VIA date -LABEL - title => 'Revenue by Category (Filtered Layers)', - x => 'Month', - y => 'Revenue ($)' -``` - -## Advanced Examples - -### Complete Regional Sales Analysis - -```{ggsql} -SELECT - sale_date, - region, - SUM(quantity) as total_quantity -FROM 'sales.csv' -WHERE sale_date >= '2023-01-01' -GROUP BY sale_date, region -ORDER BY sale_date -VISUALISE sale_date AS x, total_quantity AS y, region AS color -DRAW line -DRAW point -SCALE x VIA date -FACET region -LABEL - title => 'Sales Trends by Region', - x => 'Date', - y => 'Total Quantity' -``` - -### Multi-Category Analysis - -```{ggsql} -SELECT - category, - region, - SUM(revenue) as total_revenue -FROM 'sales.csv' -GROUP BY category, region -VISUALISE category AS x, total_revenue AS y, region AS fill -DRAW bar -LABEL - title => 'Revenue by Category and Region', - x => 'Category', - y => 'Revenue ($)' -``` diff --git a/doc/get_started/_metadata.yml b/doc/get_started/_metadata.yml index 23268da8..08d3e224 100644 --- a/doc/get_started/_metadata.yml +++ b/doc/get_started/_metadata.yml @@ -1,3 +1,3 @@ sidebar: get_started -page-navigation: false +page-navigation: true toc: false diff --git a/doc/get_started/first_plot.qmd b/doc/get_started/first_plot.qmd index d5750103..56027f6d 100644 --- a/doc/get_started/first_plot.qmd +++ b/doc/get_started/first_plot.qmd @@ -2,8 +2,6 @@ title: "Your first plot" --- -Before you spend time on the minutia of installing ggsql โ€” not that it is particularly daunting โ€” why not try it out right now, right here, in your browser? - The code below shows a simple ggsql example. But it is not just a static piece of text and an image. It is ggsql running right in your browser, using one of the built-in datasets. Try to change e.g. the title and see the plot update as you type. Even though this may be your first encounter with the ggsql syntax you might already get a sense of how some of the things fit together. See if you can change the code to instead show the different species as different shapes ```{ggsql} @@ -18,4 +16,4 @@ LABEL Congratulations! You have started your journey with ggsql! All examples you see on this site will be interactive. Please experiment to your heart's content. If you want a more dedicated exploration experience head to [our playground](wasm/) which provides a simple IDE with a number of examples to try out. -Now that you have gotten a feel for ggsql you may want to try running locally with your own data. Read on to learn how. +Before we move further, you might have some questions about the syntax. For instance, "why isn't there just a scatterplot function?". The next section will give a brief glimpse into the concept of the grammar of graphics that underpin the ggsql syntax and why we think it is a superior approach to data visualisation. diff --git a/doc/get_started/installation.qmd b/doc/get_started/installation.qmd index e5c49ba0..d22017bb 100644 --- a/doc/get_started/installation.qmd +++ b/doc/get_started/installation.qmd @@ -219,13 +219,66 @@ Download from [GitHub Releases](https://github.com/posit-dev/ggsql/releases) font-size: 0.9rem; opacity: 0.8; } + +.icon-section { + position: relative; + padding-left: 5rem; +} + +.section-icons { + position: absolute; + left: 0; + top: 0.25rem; + display: flex; + flex-direction: column; + gap: 1.5rem; +} ``` -### Command line installation +::: {.icon-section} +[![](../assets/logos/jupyter.svg){height=60} ![](../assets/logos/quarto.svg){height=60}]{.section-icons} + +### Jupyter kernel + +To use ggsql in Jupyter or Quarto notebooks, install the Jupyter kernel using either `uv` (recommended) or `cargo`. The kernel is also part of the main installer linked to above. + +#### Using uv + +[uv](https://docs.astral.sh/uv/) is the fastest way to install Rust binaries: + +```bash +uv tool install ggsql-jupyter +ggsql-jupyter --install +``` + +#### Using cargo -If you prefer installing via the command line: +If you have a Rust toolchain installed: ```bash -cargo install ggsql +cargo install ggsql-jupyter +ggsql-jupyter --install ``` +::: + +::: {.icon-section} +[![](../assets/logos/vscode.svg){height=60} ![](../assets/logos/positron.svg){height=60}]{.section-icons} + +### VS Code / Positron extension + +For syntax highlighting and language support in VS Code or Positron, install the ggsql extension. You can either install it directly from the VS Code marketplace from the IDE or install it manually: + +1. Download [`ggsql.vsix`](https://github.com/posit-dev/ggsql/releases/latest/download/ggsql.vsix) +2. Install via the command line: + +```bash +# VS Code +code --install-extension ggsql.vsix + +# Positron +positron --install-extension ggsql.vsix +``` + +Or install from within the editor: open the Extensions view, click the `...` menu, select "Install from VSIX...", and choose the downloaded file. +::: From c8fded84282861a64526b181b7c9dbd31e189467 Mon Sep 17 00:00:00 2001 From: Thomas Lin Pedersen Date: Fri, 20 Mar 2026 11:06:10 +0100 Subject: [PATCH 05/12] Fix editor style --- doc/_quarto.yml | 1 + doc/index.qmd | 126 +++++------ doc/index.quarto_ipynb_1 | 305 +++++++++++++++++++++++++++ doc/styles.scss | 130 ++++++++---- ggsql-wasm/demo/package-lock.json | 2 +- ggsql-wasm/demo/src/editor.ts | 19 +- ggsql-wasm/demo/src/quarto/editor.ts | 25 ++- 7 files changed, 496 insertions(+), 112 deletions(-) create mode 100644 doc/index.quarto_ipynb_1 diff --git a/doc/_quarto.yml b/doc/_quarto.yml index 1cbfd29c..c36f9543 100644 --- a/doc/_quarto.yml +++ b/doc/_quarto.yml @@ -125,6 +125,7 @@ website: format: html: lightbox: auto + highlight-style: pygments syntax-definitions: - ggsql.xml theme: diff --git a/doc/index.qmd b/doc/index.qmd index ca61e912..9dafef8f 100644 --- a/doc/index.qmd +++ b/doc/index.qmd @@ -24,10 +24,10 @@ include-in-header: # QUERY ![](assets/visualize.svg){.hviz aria-hidden="true"}VISUALIZE UNDERSTAND ::: {.hero-body} -ggsql brings the elegance of the Grammar of Graphics to SQL. Write familiar queries, add visualization clauses, and see your data transform into beautiful, composable charts โ€” no context switching, no separate tools, just SQL with superpowers. +ggsql brings the elegance of the [Grammar of Graphics](get_started/grammar.qmd) to SQL. Write familiar queries, add visualization clauses, and see your data transform into beautiful, composable charts โ€” no context switching, no separate tools, just SQL with superpowers. ::: {.hero-buttons} -[Get Started](get_started.qmd){.btn .btn-primary .btn-lg} +[Get Started](get_started/installation.qmd){.btn .btn-primary .btn-lg} [View Examples](gallery/index.qmd){.btn .btn-outline-primary .btn-lg} ::: ::: @@ -37,8 +37,6 @@ ggsql brings the elegance of the Grammar of Graphics to SQL. Write familiar quer ::: {.content-block .dark-bg} ### Try it out -ggsql runs in the browser as well! Edit the code and watch the plot update. - ```{ggsql} -- Regular query SELECT * FROM ggsql:penguins @@ -70,15 +68,29 @@ LABEL ::: {.content-block .dark-bg .install-section} ### Install it today -::: {#installer-buttons} +::: {.install-columns} +::: {.install-col .install-col-left} +::: {#installer-recommended} ::: -::: {.install-cli-options} -**Or via command line:** -`uv pip install ggsql-jupyter && ggsql-jupyter --install` -ยท -`cargo install ggsql` +[Other platforms](get_started/installation.qmd){.other-platforms-link} +::: + +::: {.install-divider} +[or]{.divider-text} +::: + +::: {.install-col .install-col-right} +```bash +# Jupyter kernel +uv tool install ggsql-jupyter +ggsql-jupyter --install + +# CLI +uv tool install ggsql +``` +::: ::: ```{=html} @@ -86,7 +98,7 @@ LABEL (function() { const repoOwner = 'posit-dev'; const repoName = 'ggsql'; - const includePreReleases = true; // Set to false to only show published releases + const includePreReleases = true; function detectOS() { const ua = navigator.userAgent.toLowerCase(); @@ -96,30 +108,30 @@ LABEL return 'unknown'; } - function getOSLabel(os) { - switch(os) { - case 'windows': return 'Windows'; - case 'macos': return 'macOS'; - case 'linux': return 'Linux'; - default: return 'your platform'; - } + function getOSIcon(os) { + const icons = { + windows: 'bi-windows', + macos: 'bi-apple', + linux: 'bi-ubuntu' + }; + return icons[os] ? `` : ''; } - async function loadInstallers() { - const container = document.getElementById('installer-buttons'); + const patterns = { + windows_exe: /^ggsql[_-]\d.*x64.*-setup\.exe$/i, + macos: /^ggsql[_-]\d.*(aarch64|arm64).*\.dmg$/i, + linux: /^ggsql[_-]\d.*amd64.*\.deb$/i + }; + + function findAsset(assets, pattern) { + return assets?.find(a => pattern?.test(a.name)); + } + + async function loadInstaller() { + const container = document.getElementById('installer-recommended'); if (!container) return; const os = detectOS(); - const jupyterPattern = { - windows: /ggsql-jupyter.*\.(exe|msi)$/i, - macos: /ggsql-jupyter.*\.dmg$/i, - linux: /ggsql-jupyter.*\.deb$/i - }[os]; - const cliPattern = { - windows: /^ggsql[^-].*\.(exe|msi)$/i, - macos: /^ggsql[^-].*\.dmg$/i, - linux: /^ggsql[^-].*\.deb$/i - }[os]; try { const endpoint = includePreReleases @@ -132,29 +144,25 @@ LABEL if (!release) throw new Error('No releases found'); const version = release.tag_name; - const jupyterAsset = release.assets?.find(a => jupyterPattern?.test(a.name)); - const cliAsset = release.assets?.find(a => cliPattern?.test(a.name)); + const assets = release.assets || []; + + let asset; + if (os === 'windows') { + asset = findAsset(assets, patterns.windows_exe); + } else if (os === 'macos') { + asset = findAsset(assets, patterns.macos); + } else if (os === 'linux') { + asset = findAsset(assets, patterns.linux); + } container.innerHTML = ` -

${version} ยท ${getOSLabel(os)} ยท Other platforms

-
-
- - Jupyter Kernel - -

For Jupyter and Quarto notebooks

-
-
- - CLI - -

For terminal and scripting workflows

-
-
+ + ${getOSIcon(os)} Download ggsql ${version} + `; } catch (e) { container.innerHTML = ` - + View Downloads on GitHub `; @@ -162,9 +170,9 @@ LABEL } if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', loadInstallers); + document.addEventListener('DOMContentLoaded', loadInstaller); } else { - loadInstallers(); + loadInstaller(); } })(); @@ -193,7 +201,7 @@ DRAW line ::: {.feature} ### Grammar of Graphics -Compose visualizations from independent layers, scales, and coordinates. Mix and match components for powerful custom visuals. +Compose visualizations from independent layers, scales, and coordinates. Mix and match components for powerful custom visuals. The [grammar of graphics](get_started/grammar.qmd) provides you with a single mental model for every type of plot. ```{.ggsql .code-example} VISUALISE date AS x FROM sales @@ -228,20 +236,16 @@ ggsql interfaces directly with your database. Want to create a histogram over 1 ::: {.tool-grid} ::: {.tool-item} -![](assets/logos/positron.svg){.tool-logo} -[Positron](https://positron.posit.co/) +[![](assets/logos/positron.svg){.tool-logo} Positron](get_started/installation.qmd#vs-code--positron-extension) ::: ::: {.tool-item} -![](assets/logos/quarto.svg){.tool-logo} -[Quarto](https://quarto.org/) +[![](assets/logos/quarto.svg){.tool-logo} Quarto](get_started/installation.qmd#jupyter-kernel) ::: ::: {.tool-item} -![](assets/logos/jupyter.svg){.tool-logo} -[Jupyter](https://jupyter.org) +[![](assets/logos/jupyter.svg){.tool-logo} Jupyter](get_started/installation.qmd#jupyter-kernel) ::: ::: {.tool-item} -![](assets/logos/vscode.svg){.tool-logo} -[VS Code](https://code.visualstudio.com/) +[![](assets/logos/vscode.svg){.tool-logo} VS Code](get_started/installation.qmd#vs-code--positron-extension) ::: ::: @@ -256,9 +260,9 @@ ggsql interfaces directly with your database. Want to create a histogram over 1 Install ggsql and start creating visualizations in minutes. ::: {.cta-buttons} -[Installation](get_started.qmd){.btn .btn-primary .btn-lg} +[Installation](get_started/installation.qmd){.btn .btn-primary .btn-lg} [Documentation](syntax/index.qmd){.btn .btn-outline-primary .btn-lg} -[Examples](examples.qmd){.btn .btn-outline-secondary .btn-lg} +[Examples](gallery/index.qmd){.btn .btn-outline-secondary .btn-lg} ::: Or try our [online playground](wasm/) to experience the syntax _right now_. diff --git a/doc/index.quarto_ipynb_1 b/doc/index.quarto_ipynb_1 new file mode 100644 index 00000000..7a49ac73 --- /dev/null +++ b/doc/index.quarto_ipynb_1 @@ -0,0 +1,305 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "pagetitle: \"ggsql\"\n", + "page-layout: custom\n", + "section-divs: false\n", + "toc: false\n", + "lightbox: false\n", + "repo-actions: false\n", + "listing:\n", + " - id: example-carousel\n", + " contents: gallery/examples\n", + " type: grid\n", + " grid-columns: 6\n", + " image-height: 150px\n", + " fields: [image, title]\n", + " sort: \"order\"\n", + " max-items: 6\n", + "include-in-header: \n", + " text: |\n", + " \n", + "---\n", + "\n", + "::: {.hero-banner}\n", + "\n", + "# QUERY ![](assets/visualize.svg){.hviz aria-hidden=\"true\"}VISUALIZE UNDERSTAND\n", + "\n", + "::: {.hero-body}\n", + "ggsql brings the elegance of the [Grammar of Graphics](get_started/grammar.qmd) to SQL. Write familiar queries, add visualization clauses, and see your data transform into beautiful, composable charts โ€” no context switching, no separate tools, just SQL with superpowers.\n", + "\n", + "::: {.hero-buttons}\n", + "[Get Started](get_started/installation.qmd){.btn .btn-primary .btn-lg}\n", + "[View Examples](gallery/index.qmd){.btn .btn-outline-primary .btn-lg}\n", + ":::\n", + ":::\n", + "\n", + ":::\n", + "\n", + "::: {.content-block .dark-bg}\n", + "### Try it out" + ], + "id": "e2a8b19b" + }, + { + "cell_type": "code", + "metadata": {}, + "source": [ + "-- Regular query\n", + "SELECT * FROM ggsql:penguins\n", + "WHERE island = 'Biscoe'\n", + "-- Followed by visualization declaration\n", + "VISUALISE bill_len AS x, bill_dep AS y, body_mass AS fill\n", + "DRAW point\n", + "DRAW linear \n", + " MAPPING 0.4 AS coef, -1 AS intercept\n", + "SCALE BINNED fill\n", + "LABEL\n", + " title => 'Relationship between bill dimensions in 3 species of penguins',\n", + " x => 'Bill length (mm)',\n", + " y => 'Bill depth (mm)'" + ], + "id": "ed297b4f", + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + ":::\n", + "\n", + "::: {.content-block .examples-carousel}\n", + "## Explore the examples\n", + "\n", + "::: {#example-carousel}\n", + ":::\n", + "\n", + "[See all examples โ†’](gallery/index.qmd){.see-all-link}\n", + "\n", + ":::\n", + "\n", + "::: {.content-block .dark-bg .install-section}\n", + "### Install it today\n", + "\n", + "::: {.install-columns}\n", + "::: {.install-col .install-col-left}\n", + "::: {#installer-recommended}\n", + "\n", + ":::\n", + "\n", + "[Other platforms](get_started/installation.qmd){.other-platforms-link}\n", + ":::\n", + "\n", + "::: {.install-divider}\n", + "[or]{.divider-text}\n", + ":::\n", + "\n", + "::: {.install-col .install-col-right}\n", + "```bash\n", + "# Jupyter kernel\n", + "uv tool install ggsql-jupyter\n", + "ggsql-jupyter --install\n", + "\n", + "# CLI\n", + "uv tool install ggsql\n", + "```\n", + ":::\n", + ":::\n", + "\n", + "```{=html}\n", + "\n", + "```\n", + ":::\n", + "\n", + "::: {.content-block}\n", + "## Features\n", + "\n", + "::: {.features}\n", + "\n", + "::: {.feature}\n", + "### Familiar Syntax\n", + "\n", + "Write standard SQL queries and seamlessly extend them with visualization clauses. Your existing SQL knowledge transfers directly.\n", + "\n", + "```{.ggsql .code-example}\n", + "SELECT date, revenue, region\n", + "FROM sales\n", + "WHERE year = 2024\n", + "VISUALISE date AS x, revenue AS y\n", + "DRAW line\n", + "```\n", + ":::\n", + "\n", + "::: {.feature}\n", + "### Grammar of Graphics\n", + "\n", + "Compose visualizations from independent layers, scales, and coordinates. Mix and match components for powerful custom visuals. The [grammar of graphics](get_started/grammar.qmd) provides you with a single mental model for every type of plot.\n", + "\n", + "```{.ggsql .code-example}\n", + "VISUALISE date AS x FROM sales\n", + "DRAW bar \n", + "SCALE BINNED x \n", + " SETTING breaks => 'weeks'\n", + "FACET region\n", + "```\n", + ":::\n", + "\n", + "::: {.feature}\n", + "### Built for Humans _and_ AI\n", + "\n", + "The structured syntax makes it easy for AI agents to write, and for you to read, adjust, and verify.\n", + "\n", + "You also avoid needing agents to launch full programming languages like Python or R to create powerful visualizations, so you can rest assured that the agent doesn't accidentally alter your environment in unwanted ways.\n", + ":::\n", + "\n", + "::: {.feature}\n", + "### Connect directly to your data\n", + "\n", + "ggsql interfaces directly with your database. Want to create a histogram over 1 billion observations? No problem! All calculations are pushed to the database so you only extract what is needed for the visual.\n", + ":::\n", + "\n", + ":::\n", + "\n", + ":::\n", + "\n", + "::: {.content-block .integrations}\n", + "\n", + "## Available where your data is\n", + "\n", + "::: {.tool-grid}\n", + "::: {.tool-item}\n", + "[![](assets/logos/positron.svg){.tool-logo} Positron](get_started/installation.qmd#vs-code--positron-extension)\n", + ":::\n", + "::: {.tool-item}\n", + "[![](assets/logos/quarto.svg){.tool-logo} Quarto](get_started/installation.qmd#jupyter-kernel)\n", + ":::\n", + "::: {.tool-item}\n", + "[![](assets/logos/jupyter.svg){.tool-logo} Jupyter](get_started/installation.qmd#jupyter-kernel)\n", + ":::\n", + "::: {.tool-item}\n", + "[![](assets/logos/vscode.svg){.tool-logo} VS Code](get_started/installation.qmd#vs-code--positron-extension)\n", + ":::\n", + ":::\n", + "\n", + ":::\n", + "\n", + "::: {.content-block}\n", + "\n", + "::: {.cta-section}\n", + "\n", + "## Ready to get started?\n", + "\n", + "Install ggsql and start creating visualizations in minutes.\n", + "\n", + "::: {.cta-buttons}\n", + "[Installation](get_started/installation.qmd){.btn .btn-primary .btn-lg}\n", + "[Documentation](syntax/index.qmd){.btn .btn-outline-primary .btn-lg}\n", + "[Examples](gallery/index.qmd){.btn .btn-outline-secondary .btn-lg}\n", + ":::\n", + "\n", + "Or try our [online playground](wasm/) to experience the syntax _right now_.\n", + "\n", + ":::\n", + "\n", + ":::\n" + ], + "id": "5155e097" + } + ], + "metadata": { + "kernelspec": { + "name": "ggsql", + "language": "ggsql", + "display_name": "ggsql", + "path": "/Users/thomas/Library/Jupyter/kernels/ggsql" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/doc/styles.scss b/doc/styles.scss index 9f98455c..aaaccba7 100644 --- a/doc/styles.scss +++ b/doc/styles.scss @@ -231,13 +231,13 @@ body:has(.hero-banner) { grid-template-rows: auto 1fr; column-gap: 2rem; row-gap: 0.75rem; - background: rgba(255, 255, 255, 0.85); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); + background: rgba(249, 249, 249, 0.7); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); border-radius: 16px; padding: 2rem; box-shadow: 0 8px 32px rgba(0, 95, 115, 0.1); - border: 1px solid rgba(148, 210, 189, 0.4); + border: 1px solid rgba(249, 249, 249, 0.5); transition: transform 0.3s ease, box-shadow 0.3s ease; &:hover { @@ -402,74 +402,112 @@ body:has(.hero-banner) { .install-section { text-align: center; - .install-grid { - display: grid; - grid-template-columns: 1fr; + .install-columns { + display: flex; + flex-direction: column; gap: 2rem; + align-items: center; margin-top: 1.5rem; - @media (min-width: 600px) { - grid-template-columns: 1fr 1fr; - gap: 3rem; + @media (min-width: 700px) { + flex-direction: row; + justify-content: center; + align-items: stretch; + gap: 0; } } - .install-column { - h4 { - font-size: 1.1rem; - margin-bottom: 1rem; - opacity: 0.9; + .install-col { + flex: 1; + max-width: 320px; + display: flex; + flex-direction: column; + justify-content: center; + } + + .install-col-left { + align-items: center; + } + + .install-col-right { + text-align: left; + + > p:first-child { + margin-bottom: 0.75rem; } pre { + margin: 0; + font-size: 0.85rem; text-align: left; - font-size: 0.9rem; } - } - #installer-buttons { - .install-version { - margin-bottom: 1.5rem; - font-size: 0.95rem; - opacity: 0.8; + .sourceCode { + margin: 0; } + } - .install-buttons-row { - display: flex; - gap: 2rem; - justify-content: center; - flex-wrap: wrap; - } + .install-divider { + display: none; - .install-option { + @media (min-width: 700px) { display: flex; flex-direction: column; align-items: center; - gap: 0.5rem; + justify-content: center; + padding: 0 2rem; + position: relative; + + &::before, + &::after { + content: ''; + position: absolute; + left: 50%; + width: 1px; + background: rgba(0, 95, 115, 0.2); + } + + &::before { + top: 0; + bottom: calc(50% + 1rem); + } + + &::after { + top: calc(50% + 1rem); + bottom: 0; + } + + > p { + margin: 0; + } + + .divider-text { + font-size: 0.85rem; + color: var(--brand-darkteal); + opacity: 0.7; + } } + } + + #installer-recommended { + margin-bottom: 1rem; .install-btn { - min-width: 160px; - } + min-width: 200px; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.5rem; - .install-description { - font-size: 0.85rem; - opacity: 0.7; - margin: 0; + .bi { + font-size: 1.3em; + } } } - .install-cli-options { - margin-top: 1.5rem; + .other-platforms-link { font-size: 0.9rem; - opacity: 0.85; - - code { - background: rgba(0, 95, 115, 0.08); - padding: 0.2em 0.5em; - border-radius: 4px; - font-size: 0.85em; - } + opacity: 0.8; } } diff --git a/ggsql-wasm/demo/package-lock.json b/ggsql-wasm/demo/package-lock.json index 390e98a1..2b2658ea 100644 --- a/ggsql-wasm/demo/package-lock.json +++ b/ggsql-wasm/demo/package-lock.json @@ -24,7 +24,7 @@ }, "../pkg": { "name": "ggsql-wasm", - "version": "0.1.8", + "version": "0.1.0", "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { diff --git a/ggsql-wasm/demo/src/editor.ts b/ggsql-wasm/demo/src/editor.ts index ab6e27b0..b6e14fc6 100644 --- a/ggsql-wasm/demo/src/editor.ts +++ b/ggsql-wasm/demo/src/editor.ts @@ -39,6 +39,23 @@ function scopeToMonacoToken(scopes: string[]): string { return ""; } +// Define Pygments-style theme for Monaco +monaco.editor.defineTheme("ggsql-pygments", { + base: "vs", + inherit: true, + rules: [ + { token: "comment", foreground: "408080", fontStyle: "italic" }, + { token: "string", foreground: "BA2121" }, + { token: "number", foreground: "666666" }, + { token: "keyword", foreground: "008000", fontStyle: "bold" }, + { token: "type", foreground: "008000" }, + { token: "variable", foreground: "19177C" }, + { token: "operator", foreground: "666666" }, + { token: "delimiter", foreground: "000000" }, + ], + colors: {}, +}); + async function initTextMateGrammar(): Promise { // Load oniguruma WASM const onigWasm = await fetch(WASM_BASE + "onig.wasm"); @@ -127,7 +144,7 @@ export class EditorManager { this.editor = monaco.editor.create(container, { value: initialValue, language: "ggsql", - theme: "vs", + theme: "ggsql-pygments", automaticLayout: true, minimap: { enabled: false }, fontSize: 14, diff --git a/ggsql-wasm/demo/src/quarto/editor.ts b/ggsql-wasm/demo/src/quarto/editor.ts index 61f89386..940f27c6 100644 --- a/ggsql-wasm/demo/src/quarto/editor.ts +++ b/ggsql-wasm/demo/src/quarto/editor.ts @@ -76,6 +76,25 @@ function getGrammar(): Promise { return grammarPromise; } +// Define Pygments-style theme for Monaco +monaco.editor.defineTheme("ggsql-pygments", { + base: "vs", + inherit: true, + rules: [ + { token: "comment", foreground: "408080", fontStyle: "italic" }, + { token: "string", foreground: "BA2121" }, + { token: "number", foreground: "666666" }, + { token: "keyword", foreground: "008000", fontStyle: "bold" }, + { token: "type", foreground: "008000" }, + { token: "variable", foreground: "19177C" }, + { token: "operator", foreground: "666666" }, + { token: "delimiter", foreground: "000000" }, + ], + colors: { + "editor.background": "#f7f7f7", + }, +}); + let languageRegistered = false; async function ensureLanguageRegistered(): Promise { @@ -154,7 +173,7 @@ export interface EditorInstance { editor: monaco.editor.IStandaloneCodeEditor; } -const LINE_HEIGHT = 19; +const LINE_HEIGHT = 20; const PADDING_TOP = 8; const PADDING_BOTTOM = 8; const MAX_EDITOR_HEIGHT = 400; @@ -176,14 +195,14 @@ export async function createEditor( const editor = monaco.editor.create(container, { value: initialValue, language: "ggsql", - theme: "vs", + theme: "ggsql-pygments", automaticLayout: true, minimap: { enabled: false }, fontSize: 13, lineNumbers: "on", glyphMargin: false, folding: false, - lineNumbersMinChars: 2, + lineNumbersMinChars: 3, scrollBeyondLastLine: false, wordWrap: "on", padding: { top: PADDING_TOP, bottom: PADDING_BOTTOM }, From a42810a50615001c524a5f134d4929258a7278d6 Mon Sep 17 00:00:00 2001 From: Thomas Lin Pedersen Date: Fri, 20 Mar 2026 11:08:04 +0100 Subject: [PATCH 06/12] update thumbnail to new color palette --- doc/gallery/examples/thumbnails/bar-chart.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gallery/examples/thumbnails/bar-chart.svg b/doc/gallery/examples/thumbnails/bar-chart.svg index 19dfe657..f664c45f 100644 --- a/doc/gallery/examples/thumbnails/bar-chart.svg +++ b/doc/gallery/examples/thumbnails/bar-chart.svg @@ -1 +1 @@ -AdelieChinstrapGentooSpecies050100150CountAdelieChinstrapGentoospeciesPenguin Count by Species \ No newline at end of file +AdelieChinstrapGentooSpecies050100150CountAdelieChinstrapGentoospeciesPenguin Count by Species \ No newline at end of file From 61a3f5db450e8b3cade7eea781a756344954447b Mon Sep 17 00:00:00 2001 From: Thomas Lin Pedersen Date: Fri, 20 Mar 2026 11:16:02 +0100 Subject: [PATCH 07/12] sentence case --- doc/faq.qmd | 6 +++--- doc/gallery/examples/bar-chart.qmd | 6 +++--- doc/gallery/examples/faceted.qmd | 6 +++--- doc/gallery/examples/histogram.qmd | 6 +++--- doc/gallery/examples/line-chart.qmd | 4 ++-- doc/gallery/examples/multi-layer.qmd | 6 +++--- doc/gallery/examples/scatterplot.qmd | 4 ++-- doc/gallery/index.qmd | 2 +- doc/index.qmd | 10 +++++----- doc/syntax/index.qmd | 2 +- doc/syntax/scale/aesthetic/1_color.qmd | 6 +++--- doc/syntax/scale/aesthetic/linetype.qmd | 2 +- doc/syntax/scale/aesthetic/shape.qmd | 6 +++--- 13 files changed, 33 insertions(+), 33 deletions(-) diff --git a/doc/faq.qmd b/doc/faq.qmd index 20a3488a..27b4d31c 100644 --- a/doc/faq.qmd +++ b/doc/faq.qmd @@ -1,8 +1,8 @@ --- -title: Frequently Asked Questions +title: Frequently asked questions --- -## Getting Started +## Getting started ::: {.callout-note collapse="true"} ## What is ggsql? @@ -34,7 +34,7 @@ ggsql is built in a modular way so we can gradually add new backends to it. Curr We have designed ggsql to be modular, both when it comes to the database input and the final rendering. For the first phase of the development we have chosen to use Vegalite as a renderer as it has allowed us to iterate quickly, but we do not envision Vegalite to remain the only, nor default writer in the future. ::: -## Syntax & Usage +## Syntax & usage ::: {.callout-note collapse="true"} ## What's the difference between `VISUALISE` and `VISUALIZE`? diff --git a/doc/gallery/examples/bar-chart.qmd b/doc/gallery/examples/bar-chart.qmd index 42ab2382..8dba452c 100644 --- a/doc/gallery/examples/bar-chart.qmd +++ b/doc/gallery/examples/bar-chart.qmd @@ -1,5 +1,5 @@ --- -title: "Bar Chart" +title: "Bar chart" description: "Categorical comparisons using bars" image: thumbnails/bar-chart.svg categories: [basic, bar] @@ -31,7 +31,7 @@ LABEL ## Variations -### Horizontal Bars +### Horizontal bars Use `PROJECT y, x TO cartesian` to flip the axes for horizontal bars: @@ -47,7 +47,7 @@ LABEL y => 'Count' ``` -### Auto-Count Bar Chart +### Auto-count bar chart When you don't specify a y aesthetic, ggsql automatically counts occurrences: diff --git a/doc/gallery/examples/faceted.qmd b/doc/gallery/examples/faceted.qmd index 84e204c2..c06d5f94 100644 --- a/doc/gallery/examples/faceted.qmd +++ b/doc/gallery/examples/faceted.qmd @@ -1,5 +1,5 @@ --- -title: "Faceted Plot" +title: "Faceted plot" description: "Small multiples showing data split by category" image: thumbnails/faceted.svg categories: [faceted, advanced] @@ -29,7 +29,7 @@ LABEL ## Variations -### Grid Layout with Two Variables +### Grid layout with two variables Use `FACET rows BY cols` to create a grid layout: @@ -44,7 +44,7 @@ LABEL y => 'Bill Depth (mm)' ``` -### Free Scales +### Free scales Allow each facet to have independent axis scales with `SETTING free`: diff --git a/doc/gallery/examples/histogram.qmd b/doc/gallery/examples/histogram.qmd index b2479317..256650dc 100644 --- a/doc/gallery/examples/histogram.qmd +++ b/doc/gallery/examples/histogram.qmd @@ -28,7 +28,7 @@ LABEL ## Variations -### Custom Bin Count +### Custom bin count Control the number of bins with `SETTING bins`: @@ -43,7 +43,7 @@ LABEL y => 'Count' ``` -### Custom Bin Width +### Custom bin width Set explicit bin width instead of count: @@ -58,7 +58,7 @@ LABEL y => 'Count' ``` -### Density Instead of Count +### Density instead of count Use `REMAPPING` to show density (proportion) instead of count: diff --git a/doc/gallery/examples/line-chart.qmd b/doc/gallery/examples/line-chart.qmd index e988113b..d398c755 100644 --- a/doc/gallery/examples/line-chart.qmd +++ b/doc/gallery/examples/line-chart.qmd @@ -1,5 +1,5 @@ --- -title: "Line Chart" +title: "Line chart" description: "Time series visualization with proper date scaling" image: thumbnails/line-chart.svg categories: [basic, line, time-series] @@ -31,7 +31,7 @@ LABEL ## Variations -### Multiple Lines by Category +### Multiple lines by category ```{ggsql} SELECT Date, Temp, Month FROM ggsql:airquality diff --git a/doc/gallery/examples/multi-layer.qmd b/doc/gallery/examples/multi-layer.qmd index b0a4924f..0d7f9c69 100644 --- a/doc/gallery/examples/multi-layer.qmd +++ b/doc/gallery/examples/multi-layer.qmd @@ -1,5 +1,5 @@ --- -title: "Multi-Layer Plot" +title: "Multi-layer plot" description: "Combining multiple geometric layers in one visualization" image: thumbnails/multi-layer.svg categories: [layers, advanced] @@ -33,7 +33,7 @@ LABEL ## Variations -### Different Aesthetics Per Layer +### Different aesthetics per layer Each layer can have its own aesthetic mappings using `MAPPING`: @@ -51,7 +51,7 @@ LABEL y => 'Value' ``` -### Layers from Different Data Sources +### Layers from different data sources Use `MAPPING ... FROM` to pull each layer from different CTEs: diff --git a/doc/gallery/examples/scatterplot.qmd b/doc/gallery/examples/scatterplot.qmd index e3d59100..85249711 100644 --- a/doc/gallery/examples/scatterplot.qmd +++ b/doc/gallery/examples/scatterplot.qmd @@ -1,5 +1,5 @@ --- -title: "Scatter Plot" +title: "Scatter plot" description: "Basic scatter plot mapping two numeric variables to position" image: thumbnails/scatterplot.svg categories: [basic, point] @@ -28,7 +28,7 @@ LABEL ## Variations -### With Color by Species +### With color by species ```{ggsql} VISUALISE bill_len AS x, bill_dep AS y, species AS color FROM ggsql:penguins diff --git a/doc/gallery/index.qmd b/doc/gallery/index.qmd index 5acd6f8a..41e4824e 100644 --- a/doc/gallery/index.qmd +++ b/doc/gallery/index.qmd @@ -1,5 +1,5 @@ --- -title: Example Gallery +title: Example gallery listing: contents: examples type: grid diff --git a/doc/index.qmd b/doc/index.qmd index 9dafef8f..19fca57f 100644 --- a/doc/index.qmd +++ b/doc/index.qmd @@ -27,8 +27,8 @@ include-in-header: ggsql brings the elegance of the [Grammar of Graphics](get_started/grammar.qmd) to SQL. Write familiar queries, add visualization clauses, and see your data transform into beautiful, composable charts โ€” no context switching, no separate tools, just SQL with superpowers. ::: {.hero-buttons} -[Get Started](get_started/installation.qmd){.btn .btn-primary .btn-lg} -[View Examples](gallery/index.qmd){.btn .btn-outline-primary .btn-lg} +[Get started](get_started/installation.qmd){.btn .btn-primary .btn-lg} +[View examples](gallery/index.qmd){.btn .btn-outline-primary .btn-lg} ::: ::: @@ -185,7 +185,7 @@ uv tool install ggsql ::: {.features} ::: {.feature} -### Familiar Syntax +### Familiar syntax Write standard SQL queries and seamlessly extend them with visualization clauses. Your existing SQL knowledge transfers directly. @@ -199,7 +199,7 @@ DRAW line ::: ::: {.feature} -### Grammar of Graphics +### Grammar of graphics Compose visualizations from independent layers, scales, and coordinates. Mix and match components for powerful custom visuals. The [grammar of graphics](get_started/grammar.qmd) provides you with a single mental model for every type of plot. @@ -213,7 +213,7 @@ FACET region ::: ::: {.feature} -### Built for Humans _and_ AI +### Built for humans _and_ AI The structured syntax makes it easy for AI agents to write, and for you to read, adjust, and verify. diff --git a/doc/syntax/index.qmd b/doc/syntax/index.qmd index 2827aa49..d49a43a6 100644 --- a/doc/syntax/index.qmd +++ b/doc/syntax/index.qmd @@ -2,7 +2,7 @@ title: "Syntax" --- -## Main Clauses +## Main clauses ggsql augments the standard SQL syntax with a number of new clauses to describe a visualisation. Apart from `VISUALISE` needing to be the first, the order of these clauses is arbitrary, though grouping e.g. all `DRAW` clauses will lead to queries that are easier to reason about: - [`VISUALISE`](clause/visualise.qmd) initiates the visualisation part of the query diff --git a/doc/syntax/scale/aesthetic/1_color.qmd b/doc/syntax/scale/aesthetic/1_color.qmd index c1cd601a..a05d1ffe 100644 --- a/doc/syntax/scale/aesthetic/1_color.qmd +++ b/doc/syntax/scale/aesthetic/1_color.qmd @@ -1,5 +1,5 @@ --- -title: "Fill and Stroke" +title: "Fill and stroke" format: html: toc: true @@ -161,7 +161,7 @@ Diverging palettes emphasize a critical midpoint with two contrasting hues on ei | `rdgy` | ![](examples/gradient_rdgy.svg){height=20 .lightbox} | ColorBrewer | Red-Grey | | `puor` | ![](examples/gradient_puor.svg){height=20 .lightbox} | ColorBrewer | Orange-Purple | -#### Multi-Sequential +#### Multi-sequential Multi-sequential palettes have multiple sequential segments, useful for categorical data with ordered subcategories. @@ -226,7 +226,7 @@ Bostock, M. D3.js. [d3js.org](https://d3js.org) ##### Kelly's Colors Kelly, K.L. (1965). Twenty-two colors of maximum contrast. *Color Engineering*, 3(6), 26-27. -### Choosing a Palette +### Choosing a palette #### For general continuous data diff --git a/doc/syntax/scale/aesthetic/linetype.qmd b/doc/syntax/scale/aesthetic/linetype.qmd index 0da2f877..3a77e14f 100644 --- a/doc/syntax/scale/aesthetic/linetype.qmd +++ b/doc/syntax/scale/aesthetic/linetype.qmd @@ -51,7 +51,7 @@ The `categorical` palette is the default palette for discrete linetype scales. I ### Sequential palette The `sequential` palette is the default for binned and ordinal linetype scales. It consists of up to 15 patterns with increasing amount of "on" and decreasing amount of "off". This creates a visual progression from sparse (low ink) to solid (100% ink). -#### Example: 5-Level Sequential +#### Example: 5-level sequential | Level | Pattern | Ink Density | Description | |-------|---------|-------------|-------------| diff --git a/doc/syntax/scale/aesthetic/shape.qmd b/doc/syntax/scale/aesthetic/shape.qmd index 2a40b86a..c36b6f90 100644 --- a/doc/syntax/scale/aesthetic/shape.qmd +++ b/doc/syntax/scale/aesthetic/shape.qmd @@ -56,15 +56,15 @@ DRAW point SCALE shape TO ['star', 'bowtie', 'square-plus'] ``` -### Default Palette (`closed`) +### Default palette (`closed`) The default palette contains the 9 closed shapes (first nine in the table above). This is the recommended palette for most use cases, as closed shapes are more visually prominent and easier to distinguish at small sizes. While the closed shapes are most often used filled, you can also turn if fill and only draw the stroke for a lighter look. -### Open Palette (`open`) +### Open palette (`open`) The `open` palette contains the last 6 shapes in the table. None of these have a fill. You may use this palette when you want transparent shapes that don't obscure data. -### All Shapes Palette (`shapes`) +### All shapes palette (`shapes`) This palette combines the two palettes above to provide all the possible shapes. Since not all shapes have a fill you should not map fill to anything if using this palette, and you should also be aware that differentiating 15 different shapes in the same plot will require a lot of mental effort from the viewer. ### Accessibility considerations From 0a11da64205db9711851a76d03a6825998716fb4 Mon Sep 17 00:00:00 2001 From: Thomas Lin Pedersen Date: Fri, 20 Mar 2026 11:25:15 +0100 Subject: [PATCH 08/12] playground styling --- ggsql-wasm/demo/src/index.qmd | 12 +++++++++++- ggsql-wasm/demo/src/styles.css | 14 +++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/ggsql-wasm/demo/src/index.qmd b/ggsql-wasm/demo/src/index.qmd index c72d8850..7f138f05 100644 --- a/ggsql-wasm/demo/src/index.qmd +++ b/ggsql-wasm/demo/src/index.qmd @@ -5,10 +5,20 @@ section-divs: false toc: false lightbox: false repo-actions: false -include-in-header: +include-in-header: - text: | + include-after-body: - text: | diff --git a/ggsql-wasm/demo/src/styles.css b/ggsql-wasm/demo/src/styles.css index b1567282..02a66f87 100644 --- a/ggsql-wasm/demo/src/styles.css +++ b/ggsql-wasm/demo/src/styles.css @@ -7,7 +7,7 @@ body { font-family: "Nunito Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; - height: 100vh; + height: 100dvh; overflow: hidden; background: #F9F9F9; color: #001219; @@ -17,7 +17,7 @@ body { display: grid; grid-template-columns: 200px 1fr 1fr; grid-template-rows: 1fr 150px; - height: 100vh; + height: calc(100dvh - var(--quarto-navbar-height, 0px)); gap: 1px; background: #005F73; border-top: 2px solid #005F73; @@ -31,7 +31,7 @@ body { #status { font-size: 12px; padding: 3px 10px; - border-radius: 3px; + border-radius: 0; background: #F9F9F9; color: #005F73; } @@ -119,11 +119,11 @@ body { .file-input-label { display: block; - padding: 6px 8px; + padding: 6px 12px; background: #005F73; color: #F9F9F9; text-align: center; - border-radius: 3px; + border-radius: 50rem; cursor: pointer; font-size: 12px; margin-bottom: 6px; @@ -150,12 +150,12 @@ body { .example-button { display: block; width: 100%; - padding: 5px 8px; + padding: 5px 12px; margin: 3px 0; background: #F9F9F9; border: 1px solid #94D2BD; color: #001219; - border-radius: 3px; + border-radius: 50rem; cursor: pointer; font-size: 12px; text-align: left; From ef69b36dab0fd3a5843ecfc46ee80940ed642ebd Mon Sep 17 00:00:00 2001 From: Thomas Lin Pedersen Date: Fri, 20 Mar 2026 12:13:17 +0100 Subject: [PATCH 09/12] last few tweaks --- doc/get_started/installation.qmd | 8 ++++---- ggsql-wasm/demo/src/quarto/editor.ts | 4 ++-- ggsql-wasm/demo/src/styles.css | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/doc/get_started/installation.qmd b/doc/get_started/installation.qmd index d22017bb..287854f1 100644 --- a/doc/get_started/installation.qmd +++ b/doc/get_started/installation.qmd @@ -2,7 +2,7 @@ title: "Installation" --- -While all of the examples on this website uses the ggsql web assembly build to let you run it in the browser, you likely want it on your own computer, interfacing with your local data. +While all of the examples on this website uses the ggsql WebAssembly build to let you run it in the browser, you likely want it on your own computer, interfacing with your local data. ggsql provides native installers for Windows, macOS, and Linux. Choose the best option for your platform below. @@ -245,7 +245,7 @@ To use ggsql in Jupyter or Quarto notebooks, install the Jupyter kernel using ei #### Using uv -[uv](https://docs.astral.sh/uv/) is the fastest way to install Rust binaries: +[uv](https://docs.astral.sh/uv/) is the fastest way to install the binaries: ```bash uv tool install ggsql-jupyter @@ -254,7 +254,7 @@ ggsql-jupyter --install #### Using cargo -If you have a Rust toolchain installed: +If you have a Rust toolchain installed you can install with cargo: ```bash cargo install ggsql-jupyter @@ -267,7 +267,7 @@ ggsql-jupyter --install ### VS Code / Positron extension -For syntax highlighting and language support in VS Code or Positron, install the ggsql extension. You can either install it directly from the VS Code marketplace from the IDE or install it manually: +For syntax highlighting and language support in VS Code or Positron, install the ggsql extension. You can either install it directly from the [extension marketplace](https://open-vsx.org/extension/ggsql/ggsql) from within the IDE or download and install it manually: 1. Download [`ggsql.vsix`](https://github.com/posit-dev/ggsql/releases/latest/download/ggsql.vsix) 2. Install via the command line: diff --git a/ggsql-wasm/demo/src/quarto/editor.ts b/ggsql-wasm/demo/src/quarto/editor.ts index 940f27c6..9b2db5f4 100644 --- a/ggsql-wasm/demo/src/quarto/editor.ts +++ b/ggsql-wasm/demo/src/quarto/editor.ts @@ -211,9 +211,9 @@ export async function createEditor( hideCursorInOverviewRuler: true, overviewRulerBorder: false, scrollbar: { - vertical: "auto", + vertical: "hidden", horizontal: "hidden", - verticalScrollbarSize: 8, + alwaysConsumeMouseWheel: false, }, }); diff --git a/ggsql-wasm/demo/src/styles.css b/ggsql-wasm/demo/src/styles.css index 02a66f87..7638e9de 100644 --- a/ggsql-wasm/demo/src/styles.css +++ b/ggsql-wasm/demo/src/styles.css @@ -73,6 +73,7 @@ body { .table-list { list-style: none; + padding-left: 0; } .table-item { @@ -158,7 +159,7 @@ body { border-radius: 50rem; cursor: pointer; font-size: 12px; - text-align: left; + text-align: center; } .example-button:hover { From f99a92d8f624ffaeeaed5976c2711251c779be51 Mon Sep 17 00:00:00 2001 From: Thomas Lin Pedersen Date: Fri, 20 Mar 2026 12:20:27 +0100 Subject: [PATCH 10/12] fix linking + better separation in the installation guide --- doc/faq.qmd | 2 +- doc/get_started/installation.qmd | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/faq.qmd b/doc/faq.qmd index 27b4d31c..2f28372b 100644 --- a/doc/faq.qmd +++ b/doc/faq.qmd @@ -19,7 +19,7 @@ DRAW line ::: {.callout-note collapse="true"} ## How do I install ggsql? -See the installation instruction in the [Getting started](get_started.qmd) tutorial. +See the installation instruction in the [Get started](get_started/installation.qmd) tutorial. ::: ::: {.callout-note collapse="true"} diff --git a/doc/get_started/installation.qmd b/doc/get_started/installation.qmd index 287854f1..3ed99dac 100644 --- a/doc/get_started/installation.qmd +++ b/doc/get_started/installation.qmd @@ -2,7 +2,7 @@ title: "Installation" --- -While all of the examples on this website uses the ggsql WebAssembly build to let you run it in the browser, you likely want it on your own computer, interfacing with your local data. +While all of the examples on this website uses the ggsql WebAssembly build to let you run it in the browser, you'll likely want it on your own computer, interfacing with your local data. ggsql provides native installers for Windows, macOS, and Linux. Choose the best option for your platform below. @@ -223,6 +223,7 @@ Download from [GitHub Releases](https://github.com/posit-dev/ggsql/releases) .icon-section { position: relative; padding-left: 5rem; + margin-top: 5rem } .section-icons { @@ -236,10 +237,11 @@ Download from [GitHub Releases](https://github.com/posit-dev/ggsql/releases) ``` + ::: {.icon-section} [![](../assets/logos/jupyter.svg){height=60} ![](../assets/logos/quarto.svg){height=60}]{.section-icons} -### Jupyter kernel +## Jupyter kernel To use ggsql in Jupyter or Quarto notebooks, install the Jupyter kernel using either `uv` (recommended) or `cargo`. The kernel is also part of the main installer linked to above. @@ -265,7 +267,7 @@ ggsql-jupyter --install ::: {.icon-section} [![](../assets/logos/vscode.svg){height=60} ![](../assets/logos/positron.svg){height=60}]{.section-icons} -### VS Code / Positron extension +## VS Code / Positron extension For syntax highlighting and language support in VS Code or Positron, install the ggsql extension. You can either install it directly from the [extension marketplace](https://open-vsx.org/extension/ggsql/ggsql) from within the IDE or download and install it manually: From 9b696fd7fb05566bdbb5437b6b2df3f2bd3fe24a Mon Sep 17 00:00:00 2001 From: Thomas Lin Pedersen Date: Fri, 20 Mar 2026 12:21:23 +0100 Subject: [PATCH 11/12] reformat --- src/plot/facet/types.rs | 2 +- src/plot/layer/geom/area.rs | 2 +- src/plot/layer/geom/arrow.rs | 2 +- src/plot/layer/geom/bar.rs | 2 +- src/plot/layer/geom/boxplot.rs | 5 ++--- src/plot/layer/geom/density.rs | 4 ++-- src/plot/layer/geom/errorbar.rs | 2 +- src/plot/layer/geom/histogram.rs | 2 +- src/plot/layer/geom/line.rs | 2 +- src/plot/layer/geom/linear.rs | 2 +- src/plot/layer/geom/mod.rs | 2 +- src/plot/layer/geom/path.rs | 2 +- src/plot/layer/geom/point.rs | 2 +- src/plot/layer/geom/polygon.rs | 2 +- src/plot/layer/geom/rect.rs | 2 +- src/plot/layer/geom/ribbon.rs | 2 +- src/plot/layer/geom/segment.rs | 2 +- src/plot/layer/geom/smooth.rs | 2 +- src/plot/layer/geom/text.rs | 2 +- src/plot/layer/geom/types.rs | 2 +- src/plot/layer/geom/violin.rs | 4 ++-- src/plot/layer/mod.rs | 2 +- src/plot/layer/position/dodge.rs | 7 ++----- src/plot/layer/position/jitter.rs | 12 +++--------- src/plot/layer/position/mod.rs | 2 +- src/plot/layer/position/stack.rs | 2 +- src/plot/main.rs | 2 +- src/plot/projection/coord/cartesian.rs | 2 +- src/plot/projection/coord/polar.rs | 2 +- src/plot/scale/scale_type/binned.rs | 2 +- src/plot/scale/scale_type/continuous.rs | 2 +- src/plot/scale/scale_type/discrete.rs | 2 +- src/plot/scale/scale_type/mod.rs | 2 +- src/plot/scale/scale_type/ordinal.rs | 2 +- 34 files changed, 40 insertions(+), 50 deletions(-) diff --git a/src/plot/facet/types.rs b/src/plot/facet/types.rs index 51052b9f..565802a9 100644 --- a/src/plot/facet/types.rs +++ b/src/plot/facet/types.rs @@ -2,7 +2,7 @@ //! //! This module defines faceting configuration for small multiples. -use crate::plot::types::{ParamConstraint, ParamDefinition, DefaultParamValue}; +use crate::plot::types::{DefaultParamValue, ParamConstraint, ParamDefinition}; use crate::plot::ParameterValue; use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/src/plot/layer/geom/area.rs b/src/plot/layer/geom/area.rs index d9c456d9..c16c5e63 100644 --- a/src/plot/layer/geom/area.rs +++ b/src/plot/layer/geom/area.rs @@ -2,7 +2,7 @@ use crate::plot::layer::orientation::{ALIGNED, ORIENTATION_VALUES}; use crate::plot::types::DefaultAestheticValue; -use crate::plot::{ParamDefinition, DefaultParamValue}; +use crate::plot::{DefaultParamValue, ParamDefinition}; use crate::{naming, Mappings}; use super::types::{ParamConstraint, POSITION_VALUES}; diff --git a/src/plot/layer/geom/arrow.rs b/src/plot/layer/geom/arrow.rs index 75b0a750..375d9754 100644 --- a/src/plot/layer/geom/arrow.rs +++ b/src/plot/layer/geom/arrow.rs @@ -2,7 +2,7 @@ use super::types::POSITION_VALUES; use super::{ - DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, ParamDefinition, DefaultParamValue, + DefaultAesthetics, DefaultParamValue, GeomTrait, GeomType, ParamConstraint, ParamDefinition, }; use crate::plot::types::DefaultAestheticValue; diff --git a/src/plot/layer/geom/bar.rs b/src/plot/layer/geom/bar.rs index 2cb5ec28..cddda1d4 100644 --- a/src/plot/layer/geom/bar.rs +++ b/src/plot/layer/geom/bar.rs @@ -5,7 +5,7 @@ use std::collections::HashSet; use super::types::{get_column_name, POSITION_VALUES}; use super::{ - DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, ParamDefinition, DefaultParamValue, + DefaultAesthetics, DefaultParamValue, GeomTrait, GeomType, ParamConstraint, ParamDefinition, StatResult, }; use crate::naming; diff --git a/src/plot/layer/geom/boxplot.rs b/src/plot/layer/geom/boxplot.rs index 8abdd4e0..89dcc921 100644 --- a/src/plot/layer/geom/boxplot.rs +++ b/src/plot/layer/geom/boxplot.rs @@ -7,8 +7,8 @@ use super::{DefaultAesthetics, GeomTrait, GeomType}; use crate::{ naming, plot::{ - geom::types::get_column_name, DefaultAestheticValue, ParamConstraint, ParamDefinition, - DefaultParamValue, ParameterValue, StatResult, + geom::types::get_column_name, DefaultAestheticValue, DefaultParamValue, ParamConstraint, + ParamDefinition, ParameterValue, StatResult, }, reader::SqlDialect, DataFrame, GgsqlError, Mappings, Result, @@ -496,7 +496,6 @@ mod tests { assert!(outlier_section.contains("raw.year = summary.year")); } - // ==================== GeomTrait Implementation Tests ==================== #[test] diff --git a/src/plot/layer/geom/density.rs b/src/plot/layer/geom/density.rs index 851ab49e..e67e0cbe 100644 --- a/src/plot/layer/geom/density.rs +++ b/src/plot/layer/geom/density.rs @@ -5,8 +5,8 @@ use super::{DefaultAesthetics, GeomTrait, GeomType}; use crate::{ naming, plot::{ - geom::types::get_column_name, DefaultAestheticValue, ParamConstraint, ParamDefinition, - DefaultParamValue, ParameterValue, StatResult, + geom::types::get_column_name, DefaultAestheticValue, DefaultParamValue, ParamConstraint, + ParamDefinition, ParameterValue, StatResult, }, reader::SqlDialect, GgsqlError, Mappings, Result, diff --git a/src/plot/layer/geom/errorbar.rs b/src/plot/layer/geom/errorbar.rs index f26fb464..f544504a 100644 --- a/src/plot/layer/geom/errorbar.rs +++ b/src/plot/layer/geom/errorbar.rs @@ -2,7 +2,7 @@ use super::types::POSITION_VALUES; use super::{ - DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, ParamDefinition, DefaultParamValue, + DefaultAesthetics, DefaultParamValue, GeomTrait, GeomType, ParamConstraint, ParamDefinition, }; use crate::plot::types::DefaultAestheticValue; diff --git a/src/plot/layer/geom/histogram.rs b/src/plot/layer/geom/histogram.rs index ad6b60ac..fef6fb2e 100644 --- a/src/plot/layer/geom/histogram.rs +++ b/src/plot/layer/geom/histogram.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use super::types::{get_column_name, CLOSED_VALUES, POSITION_VALUES}; use super::{ - DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, ParamDefinition, DefaultParamValue, + DefaultAesthetics, DefaultParamValue, GeomTrait, GeomType, ParamConstraint, ParamDefinition, StatResult, }; use crate::naming; diff --git a/src/plot/layer/geom/line.rs b/src/plot/layer/geom/line.rs index d0a928d0..c61a458d 100644 --- a/src/plot/layer/geom/line.rs +++ b/src/plot/layer/geom/line.rs @@ -1,7 +1,7 @@ //! Line geom implementation use super::{ - DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, ParamDefinition, DefaultParamValue, + DefaultAesthetics, DefaultParamValue, GeomTrait, GeomType, ParamConstraint, ParamDefinition, StatResult, }; use crate::plot::layer::orientation::{ALIGNED, ORIENTATION_VALUES}; diff --git a/src/plot/layer/geom/linear.rs b/src/plot/layer/geom/linear.rs index 1ae4dcb1..5867dff8 100644 --- a/src/plot/layer/geom/linear.rs +++ b/src/plot/layer/geom/linear.rs @@ -1,7 +1,7 @@ //! Linear geom implementation use super::{ - DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, ParamDefinition, DefaultParamValue, + DefaultAesthetics, DefaultParamValue, GeomTrait, GeomType, ParamConstraint, ParamDefinition, }; use crate::plot::layer::orientation::{ALIGNED, ORIENTATION_VALUES}; use crate::plot::types::DefaultAestheticValue; diff --git a/src/plot/layer/geom/mod.rs b/src/plot/layer/geom/mod.rs index 79820530..842476a1 100644 --- a/src/plot/layer/geom/mod.rs +++ b/src/plot/layer/geom/mod.rs @@ -50,7 +50,7 @@ mod violin; // Re-export types pub use types::{ - DefaultAesthetics, ParamConstraint, ParamDefinition, DefaultParamValue, StatResult, + DefaultAesthetics, DefaultParamValue, ParamConstraint, ParamDefinition, StatResult, }; // Re-export geom structs for direct access if needed diff --git a/src/plot/layer/geom/path.rs b/src/plot/layer/geom/path.rs index 8adf2152..5e32a3be 100644 --- a/src/plot/layer/geom/path.rs +++ b/src/plot/layer/geom/path.rs @@ -2,7 +2,7 @@ use super::types::POSITION_VALUES; use super::{ - DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, ParamDefinition, DefaultParamValue, + DefaultAesthetics, DefaultParamValue, GeomTrait, GeomType, ParamConstraint, ParamDefinition, }; use crate::plot::types::DefaultAestheticValue; diff --git a/src/plot/layer/geom/point.rs b/src/plot/layer/geom/point.rs index 6a2cc33b..3dafde2a 100644 --- a/src/plot/layer/geom/point.rs +++ b/src/plot/layer/geom/point.rs @@ -2,7 +2,7 @@ use super::types::POSITION_VALUES; use super::{ - DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, ParamDefinition, DefaultParamValue, + DefaultAesthetics, DefaultParamValue, GeomTrait, GeomType, ParamConstraint, ParamDefinition, }; use crate::plot::types::DefaultAestheticValue; diff --git a/src/plot/layer/geom/polygon.rs b/src/plot/layer/geom/polygon.rs index a0c60245..d1ed6841 100644 --- a/src/plot/layer/geom/polygon.rs +++ b/src/plot/layer/geom/polygon.rs @@ -2,7 +2,7 @@ use super::types::POSITION_VALUES; use super::{ - DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, ParamDefinition, DefaultParamValue, + DefaultAesthetics, DefaultParamValue, GeomTrait, GeomType, ParamConstraint, ParamDefinition, }; use crate::plot::types::DefaultAestheticValue; diff --git a/src/plot/layer/geom/rect.rs b/src/plot/layer/geom/rect.rs index a03a084e..fdd2584a 100644 --- a/src/plot/layer/geom/rect.rs +++ b/src/plot/layer/geom/rect.rs @@ -7,7 +7,7 @@ use super::types::POSITION_VALUES; use super::{DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, StatResult}; use crate::naming; use crate::plot::types::{DefaultAestheticValue, ParameterValue}; -use crate::plot::{ParamDefinition, DefaultParamValue}; +use crate::plot::{DefaultParamValue, ParamDefinition}; use crate::{DataFrame, GgsqlError, Mappings, Result}; use super::types::Schema; diff --git a/src/plot/layer/geom/ribbon.rs b/src/plot/layer/geom/ribbon.rs index e72dbf95..d3615d12 100644 --- a/src/plot/layer/geom/ribbon.rs +++ b/src/plot/layer/geom/ribbon.rs @@ -3,7 +3,7 @@ use super::types::POSITION_VALUES; use super::{DefaultAesthetics, GeomTrait, GeomType, StatResult}; use crate::plot::types::DefaultAestheticValue; -use crate::plot::{ParamConstraint, ParamDefinition, DefaultParamValue}; +use crate::plot::{DefaultParamValue, ParamConstraint, ParamDefinition}; use crate::{naming, Mappings}; /// Ribbon geom - confidence bands and ranges diff --git a/src/plot/layer/geom/segment.rs b/src/plot/layer/geom/segment.rs index 94d68a90..9506b6a1 100644 --- a/src/plot/layer/geom/segment.rs +++ b/src/plot/layer/geom/segment.rs @@ -2,7 +2,7 @@ use super::types::POSITION_VALUES; use super::{ - DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, ParamDefinition, DefaultParamValue, + DefaultAesthetics, DefaultParamValue, GeomTrait, GeomType, ParamConstraint, ParamDefinition, }; use crate::plot::types::DefaultAestheticValue; diff --git a/src/plot/layer/geom/smooth.rs b/src/plot/layer/geom/smooth.rs index f6bcf664..fad14432 100644 --- a/src/plot/layer/geom/smooth.rs +++ b/src/plot/layer/geom/smooth.rs @@ -2,7 +2,7 @@ use super::types::POSITION_VALUES; use super::{ - DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, ParamDefinition, DefaultParamValue, + DefaultAesthetics, DefaultParamValue, GeomTrait, GeomType, ParamConstraint, ParamDefinition, }; use crate::plot::geom::types::get_column_name; use crate::plot::types::DefaultAestheticValue; diff --git a/src/plot/layer/geom/text.rs b/src/plot/layer/geom/text.rs index cc0a8e84..6ceb45f9 100644 --- a/src/plot/layer/geom/text.rs +++ b/src/plot/layer/geom/text.rs @@ -2,7 +2,7 @@ use super::types::POSITION_VALUES; use super::{ - DefaultAesthetics, GeomTrait, GeomType, ParamConstraint, ParamDefinition, DefaultParamValue, + DefaultAesthetics, DefaultParamValue, GeomTrait, GeomType, ParamConstraint, ParamDefinition, ParameterValue, }; use crate::plot::types::DefaultAestheticValue; diff --git a/src/plot/layer/geom/types.rs b/src/plot/layer/geom/types.rs index 21dddb5f..ad7cf70a 100644 --- a/src/plot/layer/geom/types.rs +++ b/src/plot/layer/geom/types.rs @@ -6,7 +6,7 @@ use crate::plot::aesthetic::parse_positional; use crate::{plot::types::DefaultAestheticValue, Mappings}; // Re-export shared types from the central location -pub use crate::plot::types::{ParamConstraint, ParamDefinition, DefaultParamValue}; +pub use crate::plot::types::{DefaultParamValue, ParamConstraint, ParamDefinition}; // ============================================================================= // Common constraint value arrays diff --git a/src/plot/layer/geom/violin.rs b/src/plot/layer/geom/violin.rs index c723f9f4..bf12a393 100644 --- a/src/plot/layer/geom/violin.rs +++ b/src/plot/layer/geom/violin.rs @@ -5,8 +5,8 @@ use super::{DefaultAesthetics, GeomTrait, GeomType, StatResult}; use crate::{ naming, plot::{ - geom::types::get_column_name, DefaultAestheticValue, ParamConstraint, ParamDefinition, - DefaultParamValue, ParameterValue, + geom::types::get_column_name, DefaultAestheticValue, DefaultParamValue, ParamConstraint, + ParamDefinition, ParameterValue, }, DataFrame, GgsqlError, Mappings, Result, }; diff --git a/src/plot/layer/mod.rs b/src/plot/layer/mod.rs index 5cf34a5e..e2a9a2e1 100644 --- a/src/plot/layer/mod.rs +++ b/src/plot/layer/mod.rs @@ -20,7 +20,7 @@ pub use orientation::is_transposed; // Re-export geom types for convenience pub use geom::{ - DefaultAesthetics, Geom, GeomTrait, GeomType, ParamDefinition, DefaultParamValue, StatResult, + DefaultAesthetics, DefaultParamValue, Geom, GeomTrait, GeomType, ParamDefinition, StatResult, }; // Re-export position types for convenience diff --git a/src/plot/layer/position/dodge.rs b/src/plot/layer/position/dodge.rs index 3bcde282..ec63ba72 100644 --- a/src/plot/layer/position/dodge.rs +++ b/src/plot/layer/position/dodge.rs @@ -7,7 +7,7 @@ //! - If both are discrete โ†’ 2D grid dodge (both offsets, arranged in a grid) use super::{compute_dodge_offsets, is_continuous_scale, Layer, PositionTrait, PositionType}; -use crate::plot::types::{ParamConstraint, ParamDefinition, DefaultParamValue, ParameterValue}; +use crate::plot::types::{DefaultParamValue, ParamConstraint, ParamDefinition, ParameterValue}; use crate::{naming, DataFrame, GgsqlError, Plot, Result}; use polars::prelude::*; use std::collections::HashMap; @@ -636,9 +636,6 @@ mod tests { let params = dodge.default_params(); assert_eq!(params.len(), 1); assert_eq!(params[0].name, "width"); - assert!(matches!( - params[0].default, - DefaultParamValue::Number(0.9) - )); + assert!(matches!(params[0].default, DefaultParamValue::Number(0.9))); } } diff --git a/src/plot/layer/position/jitter.rs b/src/plot/layer/position/jitter.rs index 69e66a5d..6dcc9c80 100644 --- a/src/plot/layer/position/jitter.rs +++ b/src/plot/layer/position/jitter.rs @@ -18,7 +18,7 @@ use super::{ compute_dodge_offsets, compute_group_indices, is_continuous_scale, Layer, PositionTrait, PositionType, }; -use crate::plot::types::{ParamConstraint, ParamDefinition, DefaultParamValue, ParameterValue}; +use crate::plot::types::{DefaultParamValue, ParamConstraint, ParamDefinition, ParameterValue}; use crate::{naming, DataFrame, GgsqlError, Plot, Result}; use polars::prelude::*; use rand::Rng; @@ -996,10 +996,7 @@ mod tests { let params = jitter.default_params(); assert_eq!(params.len(), 5); assert_eq!(params[0].name, "width"); - assert!(matches!( - params[0].default, - DefaultParamValue::Number(0.9) - )); + assert!(matches!(params[0].default, DefaultParamValue::Number(0.9))); assert_eq!(params[1].name, "dodge"); assert!(matches!( params[1].default, @@ -1014,10 +1011,7 @@ mod tests { assert_eq!(params[3].name, "bandwidth"); assert!(matches!(params[3].default, DefaultParamValue::Null)); assert_eq!(params[4].name, "adjust"); - assert!(matches!( - params[4].default, - DefaultParamValue::Number(1.0) - )); + assert!(matches!(params[4].default, DefaultParamValue::Number(1.0))); } #[test] diff --git a/src/plot/layer/position/mod.rs b/src/plot/layer/position/mod.rs index 694a5d7f..af11965e 100644 --- a/src/plot/layer/position/mod.rs +++ b/src/plot/layer/position/mod.rs @@ -14,7 +14,7 @@ mod identity; mod jitter; mod stack; -use crate::plot::types::{ParamDefinition, DefaultParamValue, ParameterValue}; +use crate::plot::types::{DefaultParamValue, ParamDefinition, ParameterValue}; use crate::plot::ScaleTypeKind; use crate::{DataFrame, Plot, Result}; use serde::{Deserialize, Serialize}; diff --git a/src/plot/layer/position/stack.rs b/src/plot/layer/position/stack.rs index f669f18a..f2081e12 100644 --- a/src/plot/layer/position/stack.rs +++ b/src/plot/layer/position/stack.rs @@ -7,7 +7,7 @@ //! - If pos1 is continuous and pos2 is discrete โ†’ stack horizontally (modify pos1/pos1end) use super::{is_continuous_scale, Layer, PositionTrait, PositionType}; -use crate::plot::types::{ParamConstraint, ParamDefinition, DefaultParamValue, ParameterValue}; +use crate::plot::types::{DefaultParamValue, ParamConstraint, ParamDefinition, ParameterValue}; use crate::{naming, DataFrame, GgsqlError, Plot, Result}; use polars::prelude::*; diff --git a/src/plot/main.rs b/src/plot/main.rs index d37a418b..74360c62 100644 --- a/src/plot/main.rs +++ b/src/plot/main.rs @@ -32,7 +32,7 @@ pub use super::types::{ // Re-export Geom and related types from the layer::geom module pub use super::layer::geom::{ - DefaultAesthetics, Geom, GeomTrait, GeomType, ParamDefinition, DefaultParamValue, StatResult, + DefaultAesthetics, DefaultParamValue, Geom, GeomTrait, GeomType, ParamDefinition, StatResult, }; // Re-export Layer from the layer module diff --git a/src/plot/projection/coord/cartesian.rs b/src/plot/projection/coord/cartesian.rs index 4135febe..00d9ddf3 100644 --- a/src/plot/projection/coord/cartesian.rs +++ b/src/plot/projection/coord/cartesian.rs @@ -1,7 +1,7 @@ //! Cartesian coordinate system implementation use super::{CoordKind, CoordTrait}; -use crate::plot::types::{ParamConstraint, ParamDefinition, DefaultParamValue}; +use crate::plot::types::{DefaultParamValue, ParamConstraint, ParamDefinition}; /// Cartesian coordinate system - standard x/y coordinates #[derive(Debug, Clone, Copy)] diff --git a/src/plot/projection/coord/polar.rs b/src/plot/projection/coord/polar.rs index 94902890..4da083d1 100644 --- a/src/plot/projection/coord/polar.rs +++ b/src/plot/projection/coord/polar.rs @@ -1,7 +1,7 @@ //! Polar coordinate system implementation use super::{CoordKind, CoordTrait}; -use crate::plot::types::{ParamConstraint, ParamDefinition, DefaultParamValue}; +use crate::plot::types::{DefaultParamValue, ParamConstraint, ParamDefinition}; /// Polar coordinate system - for pie charts, rose plots #[derive(Debug, Clone, Copy)] diff --git a/src/plot/scale/scale_type/binned.rs b/src/plot/scale/scale_type/binned.rs index 3618de3f..84c5637d 100644 --- a/src/plot/scale/scale_type/binned.rs +++ b/src/plot/scale/scale_type/binned.rs @@ -9,7 +9,7 @@ use super::{ TransformKind, CLOSED_VALUES, OOB_CENSOR, OOB_SQUISH, OOB_VALUES_BINNED, }; use crate::plot::types::{ - ArrayConstraint, NumberConstraint, ParamConstraint, ParamDefinition, DefaultParamValue, + ArrayConstraint, DefaultParamValue, NumberConstraint, ParamConstraint, ParamDefinition, }; use crate::plot::{ArrayElement, ParameterValue}; diff --git a/src/plot/scale/scale_type/continuous.rs b/src/plot/scale/scale_type/continuous.rs index e5ed9d20..92f2c397 100644 --- a/src/plot/scale/scale_type/continuous.rs +++ b/src/plot/scale/scale_type/continuous.rs @@ -6,7 +6,7 @@ use super::{ ScaleTypeKind, ScaleTypeTrait, TransformKind, OOB_CENSOR, OOB_SQUISH, OOB_VALUES_CONTINUOUS, }; use crate::plot::types::{ - ArrayConstraint, NumberConstraint, ParamConstraint, ParamDefinition, DefaultParamValue, + ArrayConstraint, DefaultParamValue, NumberConstraint, ParamConstraint, ParamDefinition, }; use crate::plot::{ArrayElement, ParameterValue}; diff --git a/src/plot/scale/scale_type/discrete.rs b/src/plot/scale/scale_type/discrete.rs index ca0a36c1..ca31edfa 100644 --- a/src/plot/scale/scale_type/discrete.rs +++ b/src/plot/scale/scale_type/discrete.rs @@ -4,7 +4,7 @@ use polars::prelude::DataType; use super::super::transform::{Transform, TransformKind}; use super::{ScaleTypeKind, ScaleTypeTrait}; -use crate::plot::types::{ParamConstraint, ParamDefinition, DefaultParamValue}; +use crate::plot::types::{DefaultParamValue, ParamConstraint, ParamDefinition}; use crate::plot::ArrayElement; /// Discrete scale type - for categorical/discrete data diff --git a/src/plot/scale/scale_type/mod.rs b/src/plot/scale/scale_type/mod.rs index 2d397e39..baac8f4b 100644 --- a/src/plot/scale/scale_type/mod.rs +++ b/src/plot/scale/scale_type/mod.rs @@ -27,7 +27,7 @@ use std::sync::Arc; use super::transform::{Transform, TransformKind}; use crate::plot::aesthetic::{is_facet_aesthetic, is_positional_aesthetic}; -use crate::plot::types::{validate_parameter, ParamDefinition, DefaultParamValue}; +use crate::plot::types::{validate_parameter, DefaultParamValue, ParamDefinition}; use crate::plot::{ArrayElement, ColumnInfo, ParameterValue}; // Scale type implementations diff --git a/src/plot/scale/scale_type/ordinal.rs b/src/plot/scale/scale_type/ordinal.rs index e0121465..bc3c0d5e 100644 --- a/src/plot/scale/scale_type/ordinal.rs +++ b/src/plot/scale/scale_type/ordinal.rs @@ -8,7 +8,7 @@ use polars::prelude::DataType; use super::super::transform::{Transform, TransformKind}; use super::{ScaleTypeKind, ScaleTypeTrait}; -use crate::plot::types::{ParamConstraint, ParamDefinition, DefaultParamValue}; +use crate::plot::types::{DefaultParamValue, ParamConstraint, ParamDefinition}; use crate::plot::ArrayElement; /// Ordinal scale type - for ordered categorical data with interpolated output From 0be854f02bc3417bb0f82ab410a738eaa7e28403 Mon Sep 17 00:00:00 2001 From: Thomas Lin Pedersen Date: Fri, 20 Mar 2026 12:32:59 +0100 Subject: [PATCH 12/12] try to ignore ipynb better --- doc/.gitignore | 1 + doc/index.quarto_ipynb_1 | 305 --------------------------------------- 2 files changed, 1 insertion(+), 305 deletions(-) delete mode 100644 doc/index.quarto_ipynb_1 diff --git a/doc/.gitignore b/doc/.gitignore index 06fb2886..820772f6 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -1,4 +1,5 @@ /.quarto/ **/*.quarto_ipynb +**/*.quarto_ipynb_* _site wasm diff --git a/doc/index.quarto_ipynb_1 b/doc/index.quarto_ipynb_1 deleted file mode 100644 index 7a49ac73..00000000 --- a/doc/index.quarto_ipynb_1 +++ /dev/null @@ -1,305 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "---\n", - "pagetitle: \"ggsql\"\n", - "page-layout: custom\n", - "section-divs: false\n", - "toc: false\n", - "lightbox: false\n", - "repo-actions: false\n", - "listing:\n", - " - id: example-carousel\n", - " contents: gallery/examples\n", - " type: grid\n", - " grid-columns: 6\n", - " image-height: 150px\n", - " fields: [image, title]\n", - " sort: \"order\"\n", - " max-items: 6\n", - "include-in-header: \n", - " text: |\n", - " \n", - "---\n", - "\n", - "::: {.hero-banner}\n", - "\n", - "# QUERY ![](assets/visualize.svg){.hviz aria-hidden=\"true\"}VISUALIZE UNDERSTAND\n", - "\n", - "::: {.hero-body}\n", - "ggsql brings the elegance of the [Grammar of Graphics](get_started/grammar.qmd) to SQL. Write familiar queries, add visualization clauses, and see your data transform into beautiful, composable charts โ€” no context switching, no separate tools, just SQL with superpowers.\n", - "\n", - "::: {.hero-buttons}\n", - "[Get Started](get_started/installation.qmd){.btn .btn-primary .btn-lg}\n", - "[View Examples](gallery/index.qmd){.btn .btn-outline-primary .btn-lg}\n", - ":::\n", - ":::\n", - "\n", - ":::\n", - "\n", - "::: {.content-block .dark-bg}\n", - "### Try it out" - ], - "id": "e2a8b19b" - }, - { - "cell_type": "code", - "metadata": {}, - "source": [ - "-- Regular query\n", - "SELECT * FROM ggsql:penguins\n", - "WHERE island = 'Biscoe'\n", - "-- Followed by visualization declaration\n", - "VISUALISE bill_len AS x, bill_dep AS y, body_mass AS fill\n", - "DRAW point\n", - "DRAW linear \n", - " MAPPING 0.4 AS coef, -1 AS intercept\n", - "SCALE BINNED fill\n", - "LABEL\n", - " title => 'Relationship between bill dimensions in 3 species of penguins',\n", - " x => 'Bill length (mm)',\n", - " y => 'Bill depth (mm)'" - ], - "id": "ed297b4f", - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - ":::\n", - "\n", - "::: {.content-block .examples-carousel}\n", - "## Explore the examples\n", - "\n", - "::: {#example-carousel}\n", - ":::\n", - "\n", - "[See all examples โ†’](gallery/index.qmd){.see-all-link}\n", - "\n", - ":::\n", - "\n", - "::: {.content-block .dark-bg .install-section}\n", - "### Install it today\n", - "\n", - "::: {.install-columns}\n", - "::: {.install-col .install-col-left}\n", - "::: {#installer-recommended}\n", - "\n", - ":::\n", - "\n", - "[Other platforms](get_started/installation.qmd){.other-platforms-link}\n", - ":::\n", - "\n", - "::: {.install-divider}\n", - "[or]{.divider-text}\n", - ":::\n", - "\n", - "::: {.install-col .install-col-right}\n", - "```bash\n", - "# Jupyter kernel\n", - "uv tool install ggsql-jupyter\n", - "ggsql-jupyter --install\n", - "\n", - "# CLI\n", - "uv tool install ggsql\n", - "```\n", - ":::\n", - ":::\n", - "\n", - "```{=html}\n", - "\n", - "```\n", - ":::\n", - "\n", - "::: {.content-block}\n", - "## Features\n", - "\n", - "::: {.features}\n", - "\n", - "::: {.feature}\n", - "### Familiar Syntax\n", - "\n", - "Write standard SQL queries and seamlessly extend them with visualization clauses. Your existing SQL knowledge transfers directly.\n", - "\n", - "```{.ggsql .code-example}\n", - "SELECT date, revenue, region\n", - "FROM sales\n", - "WHERE year = 2024\n", - "VISUALISE date AS x, revenue AS y\n", - "DRAW line\n", - "```\n", - ":::\n", - "\n", - "::: {.feature}\n", - "### Grammar of Graphics\n", - "\n", - "Compose visualizations from independent layers, scales, and coordinates. Mix and match components for powerful custom visuals. The [grammar of graphics](get_started/grammar.qmd) provides you with a single mental model for every type of plot.\n", - "\n", - "```{.ggsql .code-example}\n", - "VISUALISE date AS x FROM sales\n", - "DRAW bar \n", - "SCALE BINNED x \n", - " SETTING breaks => 'weeks'\n", - "FACET region\n", - "```\n", - ":::\n", - "\n", - "::: {.feature}\n", - "### Built for Humans _and_ AI\n", - "\n", - "The structured syntax makes it easy for AI agents to write, and for you to read, adjust, and verify.\n", - "\n", - "You also avoid needing agents to launch full programming languages like Python or R to create powerful visualizations, so you can rest assured that the agent doesn't accidentally alter your environment in unwanted ways.\n", - ":::\n", - "\n", - "::: {.feature}\n", - "### Connect directly to your data\n", - "\n", - "ggsql interfaces directly with your database. Want to create a histogram over 1 billion observations? No problem! All calculations are pushed to the database so you only extract what is needed for the visual.\n", - ":::\n", - "\n", - ":::\n", - "\n", - ":::\n", - "\n", - "::: {.content-block .integrations}\n", - "\n", - "## Available where your data is\n", - "\n", - "::: {.tool-grid}\n", - "::: {.tool-item}\n", - "[![](assets/logos/positron.svg){.tool-logo} Positron](get_started/installation.qmd#vs-code--positron-extension)\n", - ":::\n", - "::: {.tool-item}\n", - "[![](assets/logos/quarto.svg){.tool-logo} Quarto](get_started/installation.qmd#jupyter-kernel)\n", - ":::\n", - "::: {.tool-item}\n", - "[![](assets/logos/jupyter.svg){.tool-logo} Jupyter](get_started/installation.qmd#jupyter-kernel)\n", - ":::\n", - "::: {.tool-item}\n", - "[![](assets/logos/vscode.svg){.tool-logo} VS Code](get_started/installation.qmd#vs-code--positron-extension)\n", - ":::\n", - ":::\n", - "\n", - ":::\n", - "\n", - "::: {.content-block}\n", - "\n", - "::: {.cta-section}\n", - "\n", - "## Ready to get started?\n", - "\n", - "Install ggsql and start creating visualizations in minutes.\n", - "\n", - "::: {.cta-buttons}\n", - "[Installation](get_started/installation.qmd){.btn .btn-primary .btn-lg}\n", - "[Documentation](syntax/index.qmd){.btn .btn-outline-primary .btn-lg}\n", - "[Examples](gallery/index.qmd){.btn .btn-outline-secondary .btn-lg}\n", - ":::\n", - "\n", - "Or try our [online playground](wasm/) to experience the syntax _right now_.\n", - "\n", - ":::\n", - "\n", - ":::\n" - ], - "id": "5155e097" - } - ], - "metadata": { - "kernelspec": { - "name": "ggsql", - "language": "ggsql", - "display_name": "ggsql", - "path": "/Users/thomas/Library/Jupyter/kernels/ggsql" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file