Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/lighthouse/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Budgets are the measured value plus roughly 20-30% headroom for CI variance.
|---|---|---|---|---|---|
| `/` | 0.63, 0.80, 0.80 | 339 KB | 114 KB | 18 KB | 2.90 MB (2.4 MB is non-script/non-font assets) |
| `/compare/` | 0.87, 0.89, 0.89 | 329 KB | 114 KB | 18 KB | 0.49 MB |
| `/playground/` (CI median, 2026-10-20, PR #825) | - | 420 KB | - | - | - |

The other audited routes (`/playground/`, `/docs/`, `/docs/getting-started/`, `/benchmarks/`, `/changelog/`) share the
same layout chunks; their per-route numbers are in the uploaded Lighthouse artifacts. The local run was cut short by
Expand All @@ -26,6 +27,11 @@ a full disk, so only `/` and `/compare/` were measured locally.
| accessibility, seo | error | 0.95 |
| best-practices | warn | 0.85 |
| resource-summary script / font / stylesheet / total | error | 420 KB / 150 KB / 25 KB / 3.6 MB |
| resource-summary script, `/playground/` only | error | 480 KB |

`/playground/` loads the CodeMirror editor and the GoSQLX highlighting bridge, so it gets its own script budget
via `assertMatrix` (the measured 420 KB plus ~15% headroom). Every other route keeps the shared 420 KB budget, and
the two matrix entries are otherwise identical: change an assertion in both when editing thresholds.

Re-measure and update this table whenever the budgets are changed.

Expand Down
38 changes: 28 additions & 10 deletions .github/lighthouse/lighthouserc.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,34 @@
{
"ci": {
"assert": {
"assertions": {
"categories:performance": ["error", { "minScore": 0.75, "aggregationMethod": "median" }],
"categories:accessibility": ["error", { "minScore": 0.95, "aggregationMethod": "median" }],
"categories:seo": ["error", { "minScore": 0.95, "aggregationMethod": "median" }],
"categories:best-practices": ["warn", { "minScore": 0.85, "aggregationMethod": "median" }],
"resource-summary:script:size": ["error", { "maxNumericValue": 420000, "aggregationMethod": "median" }],
"resource-summary:font:size": ["error", { "maxNumericValue": 150000, "aggregationMethod": "median" }],
"resource-summary:stylesheet:size": ["error", { "maxNumericValue": 25000, "aggregationMethod": "median" }],
"resource-summary:total:size": ["error", { "maxNumericValue": 3600000, "aggregationMethod": "median" }]
}
"assertMatrix": [
{
"matchingUrlPattern": "^(?!.*/playground/).*$",
"assertions": {
"categories:performance": ["error", { "minScore": 0.75, "aggregationMethod": "median" }],
"categories:accessibility": ["error", { "minScore": 0.95, "aggregationMethod": "median" }],
"categories:seo": ["error", { "minScore": 0.95, "aggregationMethod": "median" }],
"categories:best-practices": ["warn", { "minScore": 0.85, "aggregationMethod": "median" }],
"resource-summary:script:size": ["error", { "maxNumericValue": 420000, "aggregationMethod": "median" }],
"resource-summary:font:size": ["error", { "maxNumericValue": 150000, "aggregationMethod": "median" }],
"resource-summary:stylesheet:size": ["error", { "maxNumericValue": 25000, "aggregationMethod": "median" }],
"resource-summary:total:size": ["error", { "maxNumericValue": 3600000, "aggregationMethod": "median" }]
}
},
{
"matchingUrlPattern": ".*/playground/$",
"assertions": {
"categories:performance": ["error", { "minScore": 0.75, "aggregationMethod": "median" }],
"categories:accessibility": ["error", { "minScore": 0.95, "aggregationMethod": "median" }],
"categories:seo": ["error", { "minScore": 0.95, "aggregationMethod": "median" }],
"categories:best-practices": ["warn", { "minScore": 0.85, "aggregationMethod": "median" }],
"resource-summary:script:size": ["error", { "maxNumericValue": 480000, "aggregationMethod": "median" }],
"resource-summary:font:size": ["error", { "maxNumericValue": 150000, "aggregationMethod": "median" }],
"resource-summary:stylesheet:size": ["error", { "maxNumericValue": 25000, "aggregationMethod": "median" }],
"resource-summary:total:size": ["error", { "maxNumericValue": 3600000, "aggregationMethod": "median" }]
}
}
]
}
}
}
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,40 @@ acceptance, CLI refusals), so read **Behavior changes** before upgrading.
`OVER (w)`, and `WINDOW w AS (...)` no longer repeats its name inside the
parentheses. The non-standard `WINDOW w AS w2` is normalized to
`WINDOW w AS (w2)`. (#608, #629)
- **LSP semantic token legend changed**: the non-standard `identifier` token
type is replaced by the standard `variable`, which now covers table, column
and alias names and quoted identifiers (double-quoted identifiers were
`string` before). Function names are `function` and type names are `type`.
Comments and placeholders (`$1`, `?`, `:name`, `@var`) are now emitted, as
`comment` and `parameter`. AND, OR and NOT stay `keyword`. Positions are
UTF-16 code units. Clients with custom rules keyed on the old `identifier`
type (for example Neovim `@lsp.type.identifier` highlight links) must switch
to `variable`.

### Added
- **SQL syntax highlighting (`pkg/highlight`)**: `highlight.Spans(sql, opts...)`
classifies SQL into sorted, non-overlapping byte-offset spans tagged with one
of 13 stable categories (keyword, function, type, identifier,
quoted-identifier, string, number, constant, operator, punctuation, comment,
placeholder, error). It is dialect-aware via `WithDialect`, never fails
(input after the first lexical error becomes one `error` span), and detects
functions in call position and types in type position. Renderers: `ANSI` /
`WriteANSI` (256-color, true color or attributes only), `HTML` / `WriteHTML`
(classes or inline styles) and `CSS`, with `dark`, `light` and `mono` themes.
Spans marshal to JSON. Built on top of it:
- `gosqlx.Highlight`, `gosqlx.HighlightANSI` and `gosqlx.HighlightHTML`.
- `gosqlx highlight [file|SQL]` (alias `hl`, reads stdin) with
`--format ansi|html|json|css`, `--theme`, `--dialect`,
`--color auto|always|never` (honors TTY, `NO_COLOR` and `COLORTERM`) and
`--standalone` for a full HTML page.
- LSP `textDocument/semanticTokens/full` now uses `pkg/highlight` with the
standard token types (keyword, function, type, variable, string, number,
operator, comment, parameter), UTF-16 positions, per-line splitting of
multi-line tokens, and coverage of every dialect keyword and all comments.
- WASM `gosqlxHighlight(sql[, dialect])` returns spans with UTF-16 offsets;
the gosqlx.dev playground uses it for editor highlighting.

See [docs/HIGHLIGHTING.md](docs/HIGHLIGHTING.md).
- **`--dialect` flag for the `parse`, `format`, `analyze`, and `lint` CLI
commands**: dialect-specific SQL (e.g. MySQL `LIMIT offset, count`) can now be
parsed by these commands, matching the existing `validate --dialect`. Unknown
Expand Down
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ GoSQLX is a **production-ready**, **race-free**, high-performance SQL parsing SD
- **Metrics** (`pkg/metrics/`): Production performance monitoring
- **Security** (`pkg/sql/security/`): SQL injection detection with severity classification
- **Linter** (`pkg/linter/`): SQL linting engine with 30 built-in rules (L001-L030)
- **Highlight** (`pkg/highlight/`): Dialect-aware SQL syntax highlighting (spans, ANSI/HTML/CSS renderers, themes)
- **LSP** (`pkg/lsp/`): Language Server Protocol for IDE integration
- **GoSQLX** (`pkg/gosqlx/`): High-level simple API (recommended for most users)
- **Compatibility** (`pkg/compatibility/`): API stability testing
Expand Down Expand Up @@ -67,6 +68,7 @@ fingerprint→ formatter, sql/ast, sql/parser, sql/tokenizer
security → sql/ast (scanner; tests also pull parser, tokenizer)
linter → sql/parser, sql/tokenizer
# rule sub-packages additionally import: linter, models, sql/ast
highlight → models, errors, sql/keywords, sql/tokenizer
lsp → errors, models, gosqlx, sql/keywords, sql/parser, sql/tokenizer
cbinding → gosqlx, sql/ast (requires CGO; excluded from task test:race)

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ Formatting turns one-line SQL into a readable query:
- **[Parser](https://gosqlx.dev/docs/concepts/architecture/)** - zero-copy tokenizer, recursive descent parser and full AST generation.
- **[Analysis](https://gosqlx.dev/docs/reference/linting-rules/)** - SQL injection scanner, 30 lint rules (L001-L030), 20 optimizer rules and metadata extraction.
- **[Tooling](https://gosqlx.dev/docs/cli-guide/)** - AST-based formatter, query transforms API, VS Code extension and GitHub Action.
- **[Syntax highlighting](docs/HIGHLIGHTING.md)** - dialect-aware highlighting for terminals (ANSI), HTML/CSS, JSON spans, LSP semantic tokens and WASM; `gosqlx highlight query.sql` or `gosqlx.HighlightANSI(sql)`.
- **[Multi-dialect](https://gosqlx.dev/docs/reference/sql-compatibility/)** - PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, SQLite, Snowflake, ClickHouse.
- **[AI-ready](https://gosqlx.dev/docs/integrations/mcp/)** - MCP server with 7 tools, public remote endpoint, Streamable HTTP.
- **[Tested](https://gosqlx.dev/docs/reference/sql-compatibility/)** - race-detector clean in CI, ~80-85% SQL-99 (estimated).
Expand Down
Loading
Loading