Fix a few more snippets

This commit is contained in:
Simon Binder
2025-10-06 23:00:26 +02:00
parent c1366bbe31
commit c2df0a9fac
29 changed files with 1380 additions and 216 deletions
+3
View File
@@ -54,6 +54,8 @@ targets:
builders:
jaspr_content_snippets:
enabled: true
options:
process_without_directives: true
generate_for:
include:
- "lib/src/snippets/**/*.dart"
@@ -61,6 +63,7 @@ targets:
- "lib/src/snippets/*.dart"
exclude:
- "**/*.g.dart"
- "**/*.drift.dart"
auto_apply_builders: false
sources:
- "$package$"
@@ -109,7 +109,7 @@ Again, the `isNotIn` function works the other way around.
Support for common JSON operators is provided through `package:drift/extensions/json1.dart`.
This provides things like `jsonExtract` to extract fields from JSON or `jsonEach` to query
nested JSON structures. For more details, see the [JSON support](select.md#json-support) section on the page about selects or [this more complex example](../Examples/relationships.md#with-json-functions).
nested JSON structures. For more details, see the [JSON support](select.md#json-support) section on the page about selects or [this more complex example](../examples/relationships.md#with-json-functions).
## Aggregate functions (like count and sum)
@@ -181,7 +181,7 @@ This ranking can be attached to each row:
When using a `NativeDatabase`, a basic set of trigonometric functions will be available.
It also defines the `REGEXP` function, which allows you to use `a REGEXP b` in SQL queries.
For more information, see the [list of functions](../Platforms/vm.md#drift-only-functions) here.
For more information, see the [list of functions](../platforms/vm.md#drift-only-functions) here.
## Subqueries
+5 -61
View File
@@ -15,23 +15,7 @@ For each table you've specified in the `@DriftDatabase` annotation on your datab
a corresponding getter for a table will be generated. That getter can be used to
run statements:
```dart
@DriftDatabase(tables: [TodoItems, Categories])
class MyDatabase extends _$MyDatabase {
// the schemaVersion getter and the constructor from the previous page
// have been omitted.
// loads all todo entries
Future<List<TodoItem>> get allTodoItems => select(todoItems).get();
// watches all todo entries in a given category. The stream will automatically
// emit new items whenever the underlying data changes.
Stream<List<TodoItem>> watchEntriesInCategory(Category c) {
return (select(todos)..where((t) => t.category.equals(c.id))).watch();
}
}
```
<Snippet href="/lib/src/snippets/_shared/common_database.dart" name="db" />
Drift makes writing queries easy and safe. This page describes how to write basic select
queries, but also explains how to use joins and subqueries for advanced queries.
@@ -132,60 +116,20 @@ Note that the `like` check is _not_ performed in Dart - it's sent to the underly
can efficiently compute it for all rows.
## Aliases
Sometimes, a query references a table more than once. Consider the following example to store saved routes for a
navigation system:
```dart
class GeoPoints extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get name => text()();
TextColumn get latitude => text()();
TextColumn get longitude => text()();
}
class Routes extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get name => text()();
// contains the id for the start and destination geopoint.
IntColumn get start => integer()();
IntColumn get destination => integer()();
}
```
<Snippet href="/lib/src/snippets/modular/aliases.dart" name="tables" />
Now, let's say we wanted to also load the start and destination `GeoPoint` object for each route. We'd have to use
a join on the `geo-points` table twice: For the start and destination point. To express that in a query, aliases
can be used:
```dart
class RouteWithPoints {
final Route route;
final GeoPoint start;
final GeoPoint destination;
RouteWithPoints({this.route, this.start, this.destination});
}
<Snippet href="/lib/src/snippets/modular/aliases.dart" name="query" />
// inside the database class:
Future<List<RouteWithPoints>> loadRoutes() async {
// create aliases for the geoPoints table so that we can reference it twice
final start = alias(geoPoints, 's');
final destination = alias(geoPoints, 'd');
final rows = await select(routes).join([
innerJoin(start, start.id.equalsExp(routes.start)),
innerJoin(destination, destination.id.equalsExp(routes.destination)),
]).get();
return rows.map((resultRow) {
return RouteWithPoints(
route: resultRow.readTable(routes),
start: resultRow.readTable(start),
destination: resultRow.readTable(destination),
);
}).toList();
}
```
The generated statement then looks like this:
```sql
SELECT
routes.id, routes.name, routes.start, routes.destination,
+8 -10
View File
@@ -66,7 +66,7 @@ dart run build_runner build
```
Drift initializes a brand-new database with all defined tables when the database is opened for the first time. (typically when running the app for the first time)
However, if a database already exists, Drift won't make any automatic changes to its structure. Please see [migrations](../Migrations/index.md) for an overview of what to do when changing the database like this.
However, if a database already exists, Drift won't make any automatic changes to its structure. Please see [migrations](../migrations/index.md) for an overview of what to do when changing the database like this.
## Column types
@@ -87,7 +87,7 @@ Drift offers a variety of built-in column types to suit most database needs.
| `DateTime` (see [options](#datetime-options)) | `late final createdAt = dateTime()()` | `INTEGER`or `TEXT` |
| Your own | See [type converter docs](../type_converters.md). | Depending on type |
| Enums | [`intEnum` or `textEnum`](../type_converters.md#implicit-enum-converters). | `INTEGER` or `TEXT` |
| Postgres Types | See [postgres docs](../Platforms/postgres.md). | Depending on type |
| Postgres Types | See [postgres docs](../platforms/postgres.md). | Depending on type |
In addition to these basic types, columns can be configured to store any type which can be converted to a built-in type. See [type converters](../type_converters.md) for more information.
@@ -103,13 +103,11 @@ For most tables, a single auto-incrementing integer column is sufficient as the
With Drift, these columns are declared by using `autoIncrement()` in the definition of a column, which will:
<div class="annotate" markdown>
1. Make that column the sole primary-key of the table. (1)
2. Make this column automatically count up by 1 for each new row.
</div>
1. Thus, you can't use `autoIncrement()` on multiple columns, or mix
1. Make that column the sole primary-key of the table.
Thus, you can't use `autoIncrement()` on multiple columns, or mix
`autoIncrement()` and other [primary keys](#primary-keys)
2. Make this column automatically count up by 1 for each new row.
For example, when declaring a table with an auto-incrementing column:
@@ -167,7 +165,7 @@ statements.
#### `withDefault()`
Set a default value as a SQL expression that is applied in the database itself. See [expressions](../dart_api/expressions.md) for more information on how to write these expressions. Adding, removing, or changing the default value is considered a
[schema change](../Migrations/index.md) that requires special care.
[schema change](../migrations/index.md) that requires special care.
A common example for default values is to add a column describing when the row has
been created:
@@ -207,7 +205,7 @@ should happen when the target row gets updated or deleted.
Be aware that, in sqlite3, foreign key references aren't enabled by default.
They need to be enabled with `PRAGMA foreign_keys = ON`.
A suitable place to issue that pragma with drift is in a [post-migration callback](../Migrations/index.md#post-migration-callbacks).
A suitable place to issue that pragma with drift is in a [post-migration callback](../migrations/index.md#post-migration-callbacks).
### Additional validation checks
@@ -358,7 +356,7 @@ You can also add custom constraints to the table itself by overriding the `table
<Snippet href="/lib/src/snippets/dart_api/tables.dart" name="custom-constraint-table" />
!!! note "SQL Validation"
!!! success "SQL Validation"
Don't worry about syntax errors or unsupported features. Drift will validate the SQL you provide and throw an error during code generation if there are any issues.
+4 -4
View File
@@ -52,7 +52,7 @@ in your favorite dependency injection framework for flutter hence solves this pr
## Why am I getting no such table errors?
If you add another table after your app has already been installed, you need to write a [migration](Migrations/index.md)
If you add another table after your app has already been installed, you need to write a [migration](migrations/index.md)
that covers creating that table. If you're in the process of developing your app and want to use un- and reinstall your app
instead of writing migrations, that's fine too. Please note that your apps data might be backed up on Android, so
manually deleting your app's data instead of a reinstall is necessary on some devices.
@@ -60,7 +60,7 @@ manually deleting your app's data instead of a reinstall is necessary on some de
## How do I fix lints in generated files?
Based on your linter settings, you might see some warnings in the `.g.dart` files generated by drift. Since lints are mainly used for
human-written code, we recommend to disable static analysis on generated files. For that, generate a top-level file called
human-written code, we recommend to disable static analysis on generated files. For that, generate a top-level file called
`analysis_options.yaml` in your project and add this content:
```yaml
analyzer:
@@ -72,12 +72,12 @@ You might have to restart your IDE for the changes to apply.
## How can I inspect generated SQL?
All database implementations (`NativeDatabase`, `FlutterQueryExecutor`, ...) have a `logStatements` parameter that
All database implementations (`NativeDatabase`, `FlutterQueryExecutor`, ...) have a `logStatements` parameter that
you can set to `true`. When enabled, drift will print the statements it runs.
## How do I insert data on the first app start?
You can populate the database on the first start of your app with a custom [migration strategy](Migrations/index.md).
You can populate the database on the first start of your app with a custom [migration strategy](migrations/index.md).
To insert data when the database is created (which usually happens when the app is first run), you can use this:
```dart
-59
View File
@@ -31,62 +31,3 @@ and generating code.
It also links a few pages intended for developers getting started with drift, so
that you can explore the areas you're most interested in first.
## Getting Started
Here are a few things you can do to begin:
* Explore the features of `jaspr_content` inside `lib/main.dart`.
* Read the [Quick Start Guide]({{links.quickstart}}) to understand how to set up your content-driven site.
* Start adding your own content pages in the `content/` directory.
## Showcase
`jaspr_content` supports all standard markdown syntax, allowing you to format your content effectively. It also supports adding custom components like this one:
<Info>
This is an example of a custom component. You can create your own or use the ones provided by `jaspr_content` to enhance your documentation!
<Clicker/>
</Info>
### Inline Elements
Use `inline code` for brief mentions of code, **bold text** for emphasis, or *italic text* for highlighting. You can also create [links to external sites]({{links.website}}).
### Blockquotes
> This is a blockquote. It's great for highlighting important information or quotes.
> It has a custom color applied to it using `jaspr_content`s theming capabilities.
### Code Blocks
You can easily include code snippets. `jaspr_content` even comes with syntax highlighting and copy functionality out of the box.
```dart
// lib/main.dart
import 'package:jaspr/jaspr.dart';
import 'package:jaspr_content/jaspr_content.dart';
void main() {
runApp(ContentApp(
parsers: [
MarkdownParser(),
],
));
}
```
## Images
Displaying images is straightforward:
![Jasper Photo](https://jaspr.site/images/jasper_resized/17.webp)
You can even **zoom-in** by clicking on the image.
## More to Discover!
This is just a placeholder to get things started.
Feel free to explore the [Documentation]({{links.docs}}) to understand the underlying architecture and how you can customize your site further.
@@ -197,4 +197,3 @@ beforeOpen: (details) async {
await customStatement('PRAGMA foreign_keys = ON');
}
```
+6 -6
View File
@@ -25,7 +25,7 @@ adding a package to open database on the respective platform.
<Tabs defaultValue="sqlite3">
<TabItem label="Flutter (sqlite3)" value="sqlite3_flutter">
```
```yaml
dependencies:
drift: ^{{ versions.drift }}
drift_flutter: ^{{ versions.drift_flutter }}
@@ -38,14 +38,14 @@ dev_dependencies:
Alternatively, you can achieve the same result using the following command:
```
```shell
dart pub add drift drift_flutter path_provider dev:drift_dev dev:build_runner
```
</TabItem>
<TabItem label="Dart (sqlite3)" value="sqlite3">
```
```yaml
dependencies:
drift: ^{{ versions.drift }}
sqlite3: ^{{ versions.sqlite3 }}
@@ -64,7 +64,7 @@ dart pub add drift sqlite3 dev:drift_dev dev:build_runner
</TabItem>
<TabItem label="Dart (postgres)" value="postgres">
```
```yaml
dependencies:
drift: ^{{ versions.drift }}
postgres: ^{{ versions.postgres }}
@@ -84,7 +84,7 @@ dart pub add drift postgres drift_postgres dev:drift_dev dev:build_runner
Drift only generates code for sqlite3 by default. So, also create a `build.yaml`
to [configure](generation_options/index.md) `drift_dev`:
```
```yaml
targets:
$default:
builders:
@@ -187,7 +187,7 @@ started with drift:
[selects](dart_api/select.md) or [inserts, updates and deletes](dart_api/writes.md).
- Something to keep in mind for later: When changing the database, for instance by adding new columns
or tables, you need to write a migration so that existing databases are transformed to the new
format. Drift's extensive [migration tools](Migrations/index.md) help with that.
format. Drift's extensive [migration tools](migrations/index.md) help with that.
- Take a look at our [FAQ](./faq.md)! It will help you with the most common questions about drift projects.
Once you're familiar with the basics, the [overview here](index.md) shows what
+19 -29
View File
@@ -1,17 +1,8 @@
---
title: Drift files
description: Learn everything about the `.drift` files, a powerful tool to define your database in SQL.
---
Drift files are a new feature that lets you write all your database code in SQL.
But unlike raw SQL strings you might pass to simple database clients, everything in a drift file is verified
by drift's powerful SQL analyzer.
@@ -22,11 +13,11 @@ dart_apis for them so that you don't have to read back results manually.
To use this feature, lets create two files: `database.dart` and `tables.drift`. The Dart file only contains the minimum code
to setup the database:
{{ load_snippet('overview','lib/snippets/drift_files/database.dart.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/database.dart" name="overview" />
We can now declare tables and queries in the drift file:
{{ load_snippet('(full)','lib/snippets/drift_files/tables.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/tables.drift" name="(full)" />
After running the build runner with `dart run build_runner build`,
drift will write the `database.g.dart`
@@ -52,6 +43,7 @@ what we got:
`todos` and the description of the associated category.
## Variables
Inside of named queries, you can use variables just like you would expect with
sql. We support regular variables (`?`), explicitly indexed variables (`?123`)
and colon-named variables (`:id`). We don't support variables declared
@@ -63,16 +55,16 @@ When it's ambiguous, the analyzer might be unable to resolve the type of
a variable. For those scenarios, you can also denote the explicit type
of a variable:
{{ load_snippet('q1','lib/snippets/drift_files/small_snippets.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/small_snippets.drift" name="q1" />
In addition to the base type, you can also declare that the type is nullable:
{{ load_snippet('q2','lib/snippets/drift_files/small_snippets.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/small_snippets.drift" name="q2" />
Finally, you can declare that a variable should be required in Dart when using
named parameters. To do so, add a `REQUIRED` keyword:
{{ load_snippet('q3','lib/snippets/drift_files/small_snippets.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/small_snippets.drift" name="q3" />
Note that this only has an effect when the `named_parameters`
[build option](../generation_options/index.md) is
@@ -176,7 +168,7 @@ statement before it runs it.
## Imports
You can put import statements at the top of a `drift` file:
{{ load_snippet('import','lib/snippets/drift_files/small_snippets.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/small_snippets.drift" name="import" />
All tables reachable from the other file will then also be visible in
the current file and to the database that `includes` it. If you want
@@ -194,13 +186,11 @@ know from Dart.
## Nested results
Many queries fetch all columns from some table, typically by using the
`SELECT table.*` syntax. That approach can become a bit tedious when applied
over multiple tables from a join, as shown in this example:
{{ load_snippet('overview','lib/snippets/drift_files/nested.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/nested.drift" name="overview" />
To match the returned column names while avoiding name clashes in Dart, drift
will generate a class having an `id`, `name`, `id1`, `lat`, `long`, `lat1` and
@@ -208,7 +198,7 @@ a `long1` field.
Of course, that's not helpful at all - was `lat1` coming from `from` or `to`
again? Let's rewrite the query, this time using nested results:
{{ load_snippet('nested','lib/snippets/drift_files/nested.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/nested.drift" name="nested" />
As you can see, we can nest a result simply by using the drift-specific
`table.**` syntax.
@@ -247,13 +237,13 @@ Re-using the `coordinates` and `saved_routes` tables introduced in the example
for [nested results](#nested-results), we add a new table storing coordinates
along a route:
{{ load_snippet('route_points','lib/snippets/drift_files/nested.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/nested.drift" name="route_points" />
Now, assume we wanted to query a route with information about all points
along the way. While this requires two SQL statements, we can write this as a
single drift query that is then split into the two statements automatically:
{{ load_snippet('list','lib/snippets/drift_files/nested.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/nested.drift" name="list" />
This will generate a result set containing a `SavedRoute route` field along with a
`List<Point> points` list of all points along the route.
@@ -273,7 +263,7 @@ Drift files work perfectly together with drift's existing dart_api:
- you can write Dart queries for tables declared in a drift file:
{{ load_snippet('dart_interop_insert','lib/snippets/drift_files/database.dart.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/database.dart" name="dart_interop_insert" />
- by importing Dart files into a drift file, you can write sql queries for
tables declared in Dart.
@@ -291,12 +281,12 @@ You can make most of both SQL and Dart with "Dart Templates", which is a
Dart expression that gets inlined to a query at runtime. To use them, declare a
$-variable in a query:
{{ load_snippet('filterTodos','lib/snippets/modular/drift/example.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/modular/drift/example.drift" name="filterTodos" />
Drift will generate a `Selectable<Todo>` method with a `predicate` parameter that
can be used to construct dynamic filters at runtime:
{{ load_snippet('watchInCategory','lib/snippets/modular/drift/dart_example.dart.excerpt.json') }}
<Snippet href="/lib/src/snippets/modular/drift/dart_example.dart" name="watchInCategory" />
This lets you write a single SQL query and dynamically apply a predicate at runtime!
This feature works for
@@ -311,7 +301,7 @@ This feature works for
When used as expression, you can also supply a default value in your query:
{{ load_snippet('getTodos','lib/snippets/modular/drift/example.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/modular/drift/example.drift" name="getTodos" />
This will make the `predicate` parameter optional in Dart. It will use the
default SQL value (here, `TRUE`) when not explicitly set.
@@ -365,11 +355,11 @@ Of course, the [warning](../type_converters.md#implicit-enum-converters) about a
You can use custom row classes instead of having drift generate one for you.
For instance, let's say you had a Dart class defined as
{{ load_snippet('user','lib/snippets/modular/drift/row_class.dart.excerpt.json') }}
<Snippet href="/lib/src/snippets/modular/drift/row_class.dart" name="user" />
Then, you can instruct drift to use that class as a row class as follows:
{{ load_snippet('users','lib/snippets/modular/drift/with_existing.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/modular/drift/with_existing.drift" name="users" />
When using custom row classes defined in another Dart file, you also need to import that file into the file where you define
the database.
@@ -380,11 +370,11 @@ can be added after the name of the query.
For instance, let's say we expand the existing Dart code in `row_class.dart` by adding another class:
{{ load_snippet('userwithfriends','lib/snippets/modular/drift/row_class.dart.excerpt.json') }}
<Snippet href="/lib/src/snippets/modular/drift/row_class.dart" name="userwithfriends" />
Now, we can add a corresponding query using the new class for its rows:
{{ load_snippet('friends','lib/snippets/modular/drift/with_existing.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/modular/drift/with_existing.drift" name="friends" />
The `WITH UserWithFriends` syntax will make drift consider the `UserWithFriends` class.
For every field in the constructor, drift will check the column from the query and
+8 -8
View File
@@ -76,13 +76,13 @@ It's not possible to declare fts5 tables, or queries on fts5 tables, in Dart.
You can learn more about the fts5 extension on [sqlite.org](https://www.sqlite.org/fts5.html).
## geopoly
The Geopoly module is an alternative interface to the [R-Tree](https://www.sqlite.org/rtree.html) extension
that uses the [GeoJSON](https://geojson.org/) notation ([RFC-7946](https://datatracker.ietf.org/doc/html/rfc7946))
The Geopoly module is an alternative interface to the [R-Tree](https://www.sqlite.org/rtree.html) extension
that uses the [GeoJSON](https://geojson.org/) notation ([RFC-7946](https://datatracker.ietf.org/doc/html/rfc7946))
to describe two-dimensional polygons.
Geopoly includes functions for detecting when one polygon is contained within or overlaps with another,
for computing the area enclosed by a polygon,
for doing linear transformations of polygons,
for rendering polygons as [SVG](https://en.wikipedia.org/wiki/SVG),
Geopoly includes functions for detecting when one polygon is contained within or overlaps with another,
for computing the area enclosed by a polygon,
for doing linear transformations of polygons,
for rendering polygons as [SVG](https://en.wikipedia.org/wiki/SVG),
and other similar operations.
To enable the `geopoly` extension in drift files and compiled queries, modify the
@@ -93,8 +93,8 @@ An example of creating a virtual table using this extension:
```sql
create virtual table geo using geopoly(geoID, a, b);
```
Sqlite will accept any types in additional columns (`geoID`, `a`, `b` from the example above),
so `drift` will generate a `DriftAny` type for these columns, which is not always convenient.
Sqlite will accept any types in additional columns (`geoID`, `a`, `b` from the example above),
so `drift` will generate a `DriftAny` type for these columns, which is not always convenient.
To avoid this, you can add types as in this example:
```sql
create virtual table geo using geopoly (
+2 -8
View File
@@ -23,9 +23,7 @@ What's different is how tables and queries are declared. For SQL to be recognize
it needs to be put into a `.drift` file. In this example, we use a `.drift` file next to the
database class named `tables.drift`:
{{ load_snippet('(full)','lib/snippets/drift_files/getting_started/tables.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/getting_started/tables.drift" name="(full)" />
!!! note "On that AS Category"
@@ -38,15 +36,11 @@ database class named `tables.drift`:
generate a different name with the `AS <name>` declaration at the end.
Integrating drift files into the database is simple, they just need to be added to the
`include` parameter of the `@DriftDatabase` annotation. The `tables` parameter can
be omitted here, since there are no Dart-defined tables to be added to the database.
{{ load_snippet('(full)','lib/snippets/drift_files/getting_started/database.dart.excerpt.json') }}
<Snippet href="/lib/src/snippets/drift_files/getting_started/database.dart" name="(full)" />
To generate the `database.g.dart` file which contains the `_$AppDb`
superclass, run `dart run build_runner build` on the command
+3 -10
View File
@@ -1,12 +1,9 @@
---
title: Custom SQL types
description: Use custom SQL types in Drift files and Dart code.
---
Drift's core library is written with sqlite3 as a primary target. This is
reflected in the [SQL types][types] drift supports out of the box - these
types supported by sqlite3 with a few additions that are handled in Dart.
@@ -43,7 +40,7 @@ prepared statements and also be read from rows without manual conversions.
In that case, a custom type class to implement `Duration` support for drift would be
added:
{{ load_snippet('duration','lib/snippets/modular/custom_types/type.dart.excerpt.json') }}
<Snippet href="/lib/src/snippets/modular/custom_types/type.dart" name="duration" />
This type defines the following things:
@@ -61,9 +58,7 @@ This type defines the following things:
To define a custom type on a Dart table, use the `customType` column builder method with the type:
{{ load_snippet('(full)','lib/snippets/modular/custom_types/table.dart.excerpt.json') }}
<Snippet href="/lib/src/snippets/modular/custom_types/type.dart" name="(full)" />
As the example shows, other column constraints like `clientDefault` can still be added to custom
columns. You can even combine custom columns and type converters if needed.
@@ -79,9 +74,7 @@ drift doesn't have a central register describing how to deal with custom type va
In SQL, Drift's [inline Dart](drift_files.md#dart-interop) syntax may be used to define
the custom type:
{{ load_snippet('(full)','lib/snippets/modular/custom_types/drift_table.drift.excerpt.json') }}
<Snippet href="/lib/src/snippets/modular/custom_types/drift_table.drift" name="(full)" />
Please note that support for custom types in drift files is currently limited.
For instance, custom types are not currently supported in `CAST` expressions.
+13 -1
View File
@@ -5,6 +5,7 @@
@use "src/styles/details";
@use "src/styles/header";
@use "src/styles/sidebar";
@use "src/styles/constants" as c;
@use "src/jaspr";
@@ -21,6 +22,8 @@
}
.code-block {
margin: 1rem 0rem;
pre {
margin-top: 0.25rem;
border-radius: 0.375rem;
@@ -35,4 +38,13 @@
white-space: pre;
}
}
}
.boolean {
color: var(--code-pink);
}
}
.footnotes {
margin-top: 1rem;
border-top: 1px solid c.$color-separator;
}
+6 -1
View File
@@ -15,6 +15,7 @@ import 'package:watcher/watcher.dart';
// This file is generated automatically by Jaspr, do not remove or edit.
import 'jaspr_options.dart';
import 'src/common.dart';
import 'src/components/code.dart';
import 'src/components/collapsible.dart';
import 'src/components/header.dart';
@@ -61,7 +62,11 @@ void main() {
}),
],
templateEngine: MustacheTemplateEngine(),
parsers: [MarkdownParser()],
parsers: [
MarkdownParser(
documentBuilder: (_) => driftMarkdownDocumentBuilder(),
),
],
extensions: [
// Adds heading anchors to each heading.
HeadingAnchorsExtension(),
-4
View File
@@ -424,10 +424,6 @@
.content :where(figcaption):not(:where([class~=not-content],[class~=not-content] *)) {
color: var(--content-captions);
}
.content :where(p):not(:where([class~=not-content],[class~=not-content] *)) {
margin-top: 1.25em;
margin-bottom: 1.25em;
}
.content :where(blockquote):not(:where([class~=not-content],[class~=not-content] *)) {
padding-left: 1em;
margin-top: 1.6em;
+14
View File
@@ -0,0 +1,14 @@
import 'package:jaspr_content/jaspr_content.dart';
import 'package:markdown/markdown.dart' as md;
import 'components/admonition.dart';
md.Document driftMarkdownDocumentBuilder() {
return md.Document(
blockSyntaxes: [
...MarkdownParser.defaultBlockSyntaxes,
const AdmonitionSyntax(),
],
extensionSet: md.ExtensionSet.gitHubWeb,
);
}
@@ -0,0 +1,90 @@
import 'package:markdown/markdown.dart';
/// Parses blocks of the format used by Material for MkDocs
/// [Admonitions](https://squidfunk.github.io/mkdocs-material/reference/admonitions/).
final class AdmonitionSyntax extends BlockSyntax {
const AdmonitionSyntax();
@override
bool canParse(BlockParser parser) {
return pattern.hasMatch(parser.current.content);
}
@override
Node? parse(BlockParser parser) {
final match = pattern.firstMatch(parser.current.content)!;
final collapsible = match.group(1)! == '???';
final type = match.group(2)!;
final defaultTitle =
_defaultTitles[type] ??
(throw ArgumentError.value(
type,
'type',
'Unknown type. Supported are: ${_defaultTitles.keys.join(', ')}',
));
final title = match.group(3);
parser.advance();
final childLines = parseChildLines(parser);
final children = BlockParser(
childLines,
parser.document,
).parseLines(parentSyntax: this);
if (collapsible) {
return Element('details', [
Element('summary', [Text(title ?? defaultTitle)]),
...children,
])..attributes['class'] = type;
} else {
return Element('div', [
Element('p', [Text(title ?? defaultTitle)])
..attributes['class'] = 'admonition-title',
...children,
])..attributes['class'] = 'admonition $type';
}
}
@override
List<Line> parseChildLines(BlockParser parser) {
final consumed = <Line>[];
while (!parser.isDone) {
const prefix = ' ';
final content = parser.current.content;
if (content.trim().isEmpty) {
consumed.add(Line(content));
} else if (content.startsWith(prefix)) {
consumed.add(Line(content.substring(prefix.length)));
} else {
break;
}
parser.advance();
}
return consumed;
}
@override
RegExp get pattern => _pattern;
static final _pattern = RegExp(r'(!!!|\?\?\?)\s+(\w+)(?:\s+"(.*)")?');
static const _defaultTitles = {
'note': 'Note',
'abstract': 'Abstract',
'info': 'Info',
'tip': 'Tip',
'success': 'Success',
'question': 'Question',
'warning': 'Warning',
'failure': 'Failure',
'danger': 'Danger',
'bug': 'Bug',
'example': 'Example',
'quote': 'Quote',
};
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,32 @@
import 'package:drift/drift.dart';
import 'todo_tables.dart';
import 'common_database.drift.dart';
import 'todo_tables.drift.dart';
// To hide the fact that this is using the modular builder...
typedef _$MyDatabase = $MyDatabase;
// #docregion db
@DriftDatabase(tables: [TodoItems, Categories])
class MyDatabase extends _$MyDatabase {
// the schemaVersion getter and the constructor from the previous page
// have been omitted.
// #enddocregion db
MyDatabase(super.e);
@override
int get schemaVersion => throw UnimplementedError();
// #docregion db
// loads all todo entries
Future<List<TodoItem>> get allTodoItems => select(todoItems).get();
// watches all todo entries in a given category. The stream will automatically
// emit new items whenever the underlying data changes.
Stream<List<TodoItem>> watchEntriesInCategory(Category c) {
return (select(todoItems)..where((t) => t.category.equals(c.id))).watch();
}
}
// #enddocregion db
@@ -0,0 +1,29 @@
// dart format width=80
// ignore_for_file: type=lint
import 'package:drift/drift.dart' as i0;
import 'package:drift_website/src/snippets/_shared/todo_tables.drift.dart'
as i1;
abstract class $MyDatabase extends i0.GeneratedDatabase {
$MyDatabase(i0.QueryExecutor e) : super(e);
$MyDatabaseManager get managers => $MyDatabaseManager(this);
late final i1.$CategoriesTable categories = i1.$CategoriesTable(this);
late final i1.$TodoItemsTable todoItems = i1.$TodoItemsTable(this);
@override
Iterable<i0.TableInfo<i0.Table, Object?>> get allTables =>
allSchemaEntities.whereType<i0.TableInfo<i0.Table, Object?>>();
@override
List<i0.DatabaseSchemaEntity> get allSchemaEntities => [
categories,
todoItems,
];
}
class $MyDatabaseManager {
final $MyDatabase _db;
$MyDatabaseManager(this._db);
i1.$$CategoriesTableTableManager get categories =>
i1.$$CategoriesTableTableManager(_db, _db.categories);
i1.$$TodoItemsTableTableManager get todoItems =>
i1.$$TodoItemsTableTableManager(_db, _db.todoItems);
}
@@ -0,0 +1,64 @@
import 'package:drift/drift.dart';
import 'aliases.drift.dart';
// #docregion tables
class GeoPoints extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get name => text()();
TextColumn get latitude => text()();
TextColumn get longitude => text()();
}
class Routes extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get name => text()();
// contains the id for the start and destination geopoint.
IntColumn get start => integer()();
IntColumn get destination => integer()();
}
// #enddocregion tables
// #docregion query
class RouteWithPoints {
final Route route;
final GeoPoint start;
final GeoPoint destination;
RouteWithPoints({
required this.route,
required this.start,
required this.destination,
});
}
// #enddocregion query
extension FakeDatabase on GeneratedDatabase {
$GeoPointsTable get geoPoints => throw '';
$RoutesTable get routes => throw '';
// #docregion query
// inside the database class:
Future<List<RouteWithPoints>> loadRoutes() async {
// create aliases for the geoPoints table so that we can reference it twice
final start = alias(geoPoints, 's');
final destination = alias(geoPoints, 'd');
final rows = await select(routes).join([
innerJoin(start, start.id.equalsExp(routes.start)),
innerJoin(destination, destination.id.equalsExp(routes.destination)),
]).get();
return rows.map((resultRow) {
return RouteWithPoints(
route: resultRow.readTable(routes),
start: resultRow.readTable(start),
destination: resultRow.readTable(destination),
);
}).toList();
}
// #enddocregion query
}
@@ -0,0 +1,968 @@
// dart format width=80
// ignore_for_file: type=lint
import 'package:drift/drift.dart' as i0;
import 'package:drift_website/src/snippets/modular/aliases.drift.dart' as i1;
import 'package:drift_website/src/snippets/modular/aliases.dart' as i2;
typedef $$GeoPointsTableCreateCompanionBuilder =
i1.GeoPointsCompanion Function({
i0.Value<int> id,
required String name,
required String latitude,
required String longitude,
});
typedef $$GeoPointsTableUpdateCompanionBuilder =
i1.GeoPointsCompanion Function({
i0.Value<int> id,
i0.Value<String> name,
i0.Value<String> latitude,
i0.Value<String> longitude,
});
class $$GeoPointsTableFilterComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$GeoPointsTable> {
$$GeoPointsTableFilterComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.ColumnFilters<int> get id => $composableBuilder(
column: $table.id,
builder: (column) => i0.ColumnFilters(column),
);
i0.ColumnFilters<String> get name => $composableBuilder(
column: $table.name,
builder: (column) => i0.ColumnFilters(column),
);
i0.ColumnFilters<String> get latitude => $composableBuilder(
column: $table.latitude,
builder: (column) => i0.ColumnFilters(column),
);
i0.ColumnFilters<String> get longitude => $composableBuilder(
column: $table.longitude,
builder: (column) => i0.ColumnFilters(column),
);
}
class $$GeoPointsTableOrderingComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$GeoPointsTable> {
$$GeoPointsTableOrderingComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.ColumnOrderings<int> get id => $composableBuilder(
column: $table.id,
builder: (column) => i0.ColumnOrderings(column),
);
i0.ColumnOrderings<String> get name => $composableBuilder(
column: $table.name,
builder: (column) => i0.ColumnOrderings(column),
);
i0.ColumnOrderings<String> get latitude => $composableBuilder(
column: $table.latitude,
builder: (column) => i0.ColumnOrderings(column),
);
i0.ColumnOrderings<String> get longitude => $composableBuilder(
column: $table.longitude,
builder: (column) => i0.ColumnOrderings(column),
);
}
class $$GeoPointsTableAnnotationComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$GeoPointsTable> {
$$GeoPointsTableAnnotationComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.GeneratedColumn<int> get id =>
$composableBuilder(column: $table.id, builder: (column) => column);
i0.GeneratedColumn<String> get name =>
$composableBuilder(column: $table.name, builder: (column) => column);
i0.GeneratedColumn<String> get latitude =>
$composableBuilder(column: $table.latitude, builder: (column) => column);
i0.GeneratedColumn<String> get longitude =>
$composableBuilder(column: $table.longitude, builder: (column) => column);
}
class $$GeoPointsTableTableManager
extends
i0.RootTableManager<
i0.GeneratedDatabase,
i1.$GeoPointsTable,
i1.GeoPoint,
i1.$$GeoPointsTableFilterComposer,
i1.$$GeoPointsTableOrderingComposer,
i1.$$GeoPointsTableAnnotationComposer,
$$GeoPointsTableCreateCompanionBuilder,
$$GeoPointsTableUpdateCompanionBuilder,
(
i1.GeoPoint,
i0.BaseReferences<
i0.GeneratedDatabase,
i1.$GeoPointsTable,
i1.GeoPoint
>,
),
i1.GeoPoint,
i0.PrefetchHooks Function()
> {
$$GeoPointsTableTableManager(
i0.GeneratedDatabase db,
i1.$GeoPointsTable table,
) : super(
i0.TableManagerState(
db: db,
table: table,
createFilteringComposer: () =>
i1.$$GeoPointsTableFilterComposer($db: db, $table: table),
createOrderingComposer: () =>
i1.$$GeoPointsTableOrderingComposer($db: db, $table: table),
createComputedFieldComposer: () =>
i1.$$GeoPointsTableAnnotationComposer($db: db, $table: table),
updateCompanionCallback:
({
i0.Value<int> id = const i0.Value.absent(),
i0.Value<String> name = const i0.Value.absent(),
i0.Value<String> latitude = const i0.Value.absent(),
i0.Value<String> longitude = const i0.Value.absent(),
}) => i1.GeoPointsCompanion(
id: id,
name: name,
latitude: latitude,
longitude: longitude,
),
createCompanionCallback:
({
i0.Value<int> id = const i0.Value.absent(),
required String name,
required String latitude,
required String longitude,
}) => i1.GeoPointsCompanion.insert(
id: id,
name: name,
latitude: latitude,
longitude: longitude,
),
withReferenceMapper: (p0) => p0
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e)))
.toList(),
prefetchHooksCallback: null,
),
);
}
typedef $$GeoPointsTableProcessedTableManager =
i0.ProcessedTableManager<
i0.GeneratedDatabase,
i1.$GeoPointsTable,
i1.GeoPoint,
i1.$$GeoPointsTableFilterComposer,
i1.$$GeoPointsTableOrderingComposer,
i1.$$GeoPointsTableAnnotationComposer,
$$GeoPointsTableCreateCompanionBuilder,
$$GeoPointsTableUpdateCompanionBuilder,
(
i1.GeoPoint,
i0.BaseReferences<
i0.GeneratedDatabase,
i1.$GeoPointsTable,
i1.GeoPoint
>,
),
i1.GeoPoint,
i0.PrefetchHooks Function()
>;
typedef $$RoutesTableCreateCompanionBuilder =
i1.RoutesCompanion Function({
i0.Value<int> id,
required String name,
required int start,
required int destination,
});
typedef $$RoutesTableUpdateCompanionBuilder =
i1.RoutesCompanion Function({
i0.Value<int> id,
i0.Value<String> name,
i0.Value<int> start,
i0.Value<int> destination,
});
class $$RoutesTableFilterComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$RoutesTable> {
$$RoutesTableFilterComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.ColumnFilters<int> get id => $composableBuilder(
column: $table.id,
builder: (column) => i0.ColumnFilters(column),
);
i0.ColumnFilters<String> get name => $composableBuilder(
column: $table.name,
builder: (column) => i0.ColumnFilters(column),
);
i0.ColumnFilters<int> get start => $composableBuilder(
column: $table.start,
builder: (column) => i0.ColumnFilters(column),
);
i0.ColumnFilters<int> get destination => $composableBuilder(
column: $table.destination,
builder: (column) => i0.ColumnFilters(column),
);
}
class $$RoutesTableOrderingComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$RoutesTable> {
$$RoutesTableOrderingComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.ColumnOrderings<int> get id => $composableBuilder(
column: $table.id,
builder: (column) => i0.ColumnOrderings(column),
);
i0.ColumnOrderings<String> get name => $composableBuilder(
column: $table.name,
builder: (column) => i0.ColumnOrderings(column),
);
i0.ColumnOrderings<int> get start => $composableBuilder(
column: $table.start,
builder: (column) => i0.ColumnOrderings(column),
);
i0.ColumnOrderings<int> get destination => $composableBuilder(
column: $table.destination,
builder: (column) => i0.ColumnOrderings(column),
);
}
class $$RoutesTableAnnotationComposer
extends i0.Composer<i0.GeneratedDatabase, i1.$RoutesTable> {
$$RoutesTableAnnotationComposer({
required super.$db,
required super.$table,
super.joinBuilder,
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.GeneratedColumn<int> get id =>
$composableBuilder(column: $table.id, builder: (column) => column);
i0.GeneratedColumn<String> get name =>
$composableBuilder(column: $table.name, builder: (column) => column);
i0.GeneratedColumn<int> get start =>
$composableBuilder(column: $table.start, builder: (column) => column);
i0.GeneratedColumn<int> get destination => $composableBuilder(
column: $table.destination,
builder: (column) => column,
);
}
class $$RoutesTableTableManager
extends
i0.RootTableManager<
i0.GeneratedDatabase,
i1.$RoutesTable,
i1.Route,
i1.$$RoutesTableFilterComposer,
i1.$$RoutesTableOrderingComposer,
i1.$$RoutesTableAnnotationComposer,
$$RoutesTableCreateCompanionBuilder,
$$RoutesTableUpdateCompanionBuilder,
(
i1.Route,
i0.BaseReferences<i0.GeneratedDatabase, i1.$RoutesTable, i1.Route>,
),
i1.Route,
i0.PrefetchHooks Function()
> {
$$RoutesTableTableManager(i0.GeneratedDatabase db, i1.$RoutesTable table)
: super(
i0.TableManagerState(
db: db,
table: table,
createFilteringComposer: () =>
i1.$$RoutesTableFilterComposer($db: db, $table: table),
createOrderingComposer: () =>
i1.$$RoutesTableOrderingComposer($db: db, $table: table),
createComputedFieldComposer: () =>
i1.$$RoutesTableAnnotationComposer($db: db, $table: table),
updateCompanionCallback:
({
i0.Value<int> id = const i0.Value.absent(),
i0.Value<String> name = const i0.Value.absent(),
i0.Value<int> start = const i0.Value.absent(),
i0.Value<int> destination = const i0.Value.absent(),
}) => i1.RoutesCompanion(
id: id,
name: name,
start: start,
destination: destination,
),
createCompanionCallback:
({
i0.Value<int> id = const i0.Value.absent(),
required String name,
required int start,
required int destination,
}) => i1.RoutesCompanion.insert(
id: id,
name: name,
start: start,
destination: destination,
),
withReferenceMapper: (p0) => p0
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e)))
.toList(),
prefetchHooksCallback: null,
),
);
}
typedef $$RoutesTableProcessedTableManager =
i0.ProcessedTableManager<
i0.GeneratedDatabase,
i1.$RoutesTable,
i1.Route,
i1.$$RoutesTableFilterComposer,
i1.$$RoutesTableOrderingComposer,
i1.$$RoutesTableAnnotationComposer,
$$RoutesTableCreateCompanionBuilder,
$$RoutesTableUpdateCompanionBuilder,
(
i1.Route,
i0.BaseReferences<i0.GeneratedDatabase, i1.$RoutesTable, i1.Route>,
),
i1.Route,
i0.PrefetchHooks Function()
>;
class $GeoPointsTable extends i2.GeoPoints
with i0.TableInfo<$GeoPointsTable, i1.GeoPoint> {
@override
final i0.GeneratedDatabase attachedDatabase;
final String? _alias;
$GeoPointsTable(this.attachedDatabase, [this._alias]);
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
@override
late final i0.GeneratedColumn<int> id = i0.GeneratedColumn<int>(
'id',
aliasedName,
false,
hasAutoIncrement: true,
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
'PRIMARY KEY AUTOINCREMENT',
),
);
static const i0.VerificationMeta _nameMeta = const i0.VerificationMeta(
'name',
);
@override
late final i0.GeneratedColumn<String> name = i0.GeneratedColumn<String>(
'name',
aliasedName,
false,
type: i0.DriftSqlType.string,
requiredDuringInsert: true,
);
static const i0.VerificationMeta _latitudeMeta = const i0.VerificationMeta(
'latitude',
);
@override
late final i0.GeneratedColumn<String> latitude = i0.GeneratedColumn<String>(
'latitude',
aliasedName,
false,
type: i0.DriftSqlType.string,
requiredDuringInsert: true,
);
static const i0.VerificationMeta _longitudeMeta = const i0.VerificationMeta(
'longitude',
);
@override
late final i0.GeneratedColumn<String> longitude = i0.GeneratedColumn<String>(
'longitude',
aliasedName,
false,
type: i0.DriftSqlType.string,
requiredDuringInsert: true,
);
@override
List<i0.GeneratedColumn> get $columns => [id, name, latitude, longitude];
@override
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => $name;
static const String $name = 'geo_points';
@override
i0.VerificationContext validateIntegrity(
i0.Insertable<i1.GeoPoint> instance, {
bool isInserting = false,
}) {
final context = i0.VerificationContext();
final data = instance.toColumns(true);
if (data.containsKey('id')) {
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
}
if (data.containsKey('name')) {
context.handle(
_nameMeta,
name.isAcceptableOrUnknown(data['name']!, _nameMeta),
);
} else if (isInserting) {
context.missing(_nameMeta);
}
if (data.containsKey('latitude')) {
context.handle(
_latitudeMeta,
latitude.isAcceptableOrUnknown(data['latitude']!, _latitudeMeta),
);
} else if (isInserting) {
context.missing(_latitudeMeta);
}
if (data.containsKey('longitude')) {
context.handle(
_longitudeMeta,
longitude.isAcceptableOrUnknown(data['longitude']!, _longitudeMeta),
);
} else if (isInserting) {
context.missing(_longitudeMeta);
}
return context;
}
@override
Set<i0.GeneratedColumn> get $primaryKey => {id};
@override
i1.GeoPoint map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return i1.GeoPoint(
id: attachedDatabase.typeMapping.read(
i0.DriftSqlType.int,
data['${effectivePrefix}id'],
)!,
name: attachedDatabase.typeMapping.read(
i0.DriftSqlType.string,
data['${effectivePrefix}name'],
)!,
latitude: attachedDatabase.typeMapping.read(
i0.DriftSqlType.string,
data['${effectivePrefix}latitude'],
)!,
longitude: attachedDatabase.typeMapping.read(
i0.DriftSqlType.string,
data['${effectivePrefix}longitude'],
)!,
);
}
@override
$GeoPointsTable createAlias(String alias) {
return $GeoPointsTable(attachedDatabase, alias);
}
}
class GeoPoint extends i0.DataClass implements i0.Insertable<i1.GeoPoint> {
final int id;
final String name;
final String latitude;
final String longitude;
const GeoPoint({
required this.id,
required this.name,
required this.latitude,
required this.longitude,
});
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
map['id'] = i0.Variable<int>(id);
map['name'] = i0.Variable<String>(name);
map['latitude'] = i0.Variable<String>(latitude);
map['longitude'] = i0.Variable<String>(longitude);
return map;
}
i1.GeoPointsCompanion toCompanion(bool nullToAbsent) {
return i1.GeoPointsCompanion(
id: i0.Value(id),
name: i0.Value(name),
latitude: i0.Value(latitude),
longitude: i0.Value(longitude),
);
}
factory GeoPoint.fromJson(
Map<String, dynamic> json, {
i0.ValueSerializer? serializer,
}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return GeoPoint(
id: serializer.fromJson<int>(json['id']),
name: serializer.fromJson<String>(json['name']),
latitude: serializer.fromJson<String>(json['latitude']),
longitude: serializer.fromJson<String>(json['longitude']),
);
}
@override
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'name': serializer.toJson<String>(name),
'latitude': serializer.toJson<String>(latitude),
'longitude': serializer.toJson<String>(longitude),
};
}
i1.GeoPoint copyWith({
int? id,
String? name,
String? latitude,
String? longitude,
}) => i1.GeoPoint(
id: id ?? this.id,
name: name ?? this.name,
latitude: latitude ?? this.latitude,
longitude: longitude ?? this.longitude,
);
GeoPoint copyWithCompanion(i1.GeoPointsCompanion data) {
return GeoPoint(
id: data.id.present ? data.id.value : this.id,
name: data.name.present ? data.name.value : this.name,
latitude: data.latitude.present ? data.latitude.value : this.latitude,
longitude: data.longitude.present ? data.longitude.value : this.longitude,
);
}
@override
String toString() {
return (StringBuffer('GeoPoint(')
..write('id: $id, ')
..write('name: $name, ')
..write('latitude: $latitude, ')
..write('longitude: $longitude')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(id, name, latitude, longitude);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is i1.GeoPoint &&
other.id == this.id &&
other.name == this.name &&
other.latitude == this.latitude &&
other.longitude == this.longitude);
}
class GeoPointsCompanion extends i0.UpdateCompanion<i1.GeoPoint> {
final i0.Value<int> id;
final i0.Value<String> name;
final i0.Value<String> latitude;
final i0.Value<String> longitude;
const GeoPointsCompanion({
this.id = const i0.Value.absent(),
this.name = const i0.Value.absent(),
this.latitude = const i0.Value.absent(),
this.longitude = const i0.Value.absent(),
});
GeoPointsCompanion.insert({
this.id = const i0.Value.absent(),
required String name,
required String latitude,
required String longitude,
}) : name = i0.Value(name),
latitude = i0.Value(latitude),
longitude = i0.Value(longitude);
static i0.Insertable<i1.GeoPoint> custom({
i0.Expression<int>? id,
i0.Expression<String>? name,
i0.Expression<String>? latitude,
i0.Expression<String>? longitude,
}) {
return i0.RawValuesInsertable({
if (id != null) 'id': id,
if (name != null) 'name': name,
if (latitude != null) 'latitude': latitude,
if (longitude != null) 'longitude': longitude,
});
}
i1.GeoPointsCompanion copyWith({
i0.Value<int>? id,
i0.Value<String>? name,
i0.Value<String>? latitude,
i0.Value<String>? longitude,
}) {
return i1.GeoPointsCompanion(
id: id ?? this.id,
name: name ?? this.name,
latitude: latitude ?? this.latitude,
longitude: longitude ?? this.longitude,
);
}
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
if (id.present) {
map['id'] = i0.Variable<int>(id.value);
}
if (name.present) {
map['name'] = i0.Variable<String>(name.value);
}
if (latitude.present) {
map['latitude'] = i0.Variable<String>(latitude.value);
}
if (longitude.present) {
map['longitude'] = i0.Variable<String>(longitude.value);
}
return map;
}
@override
String toString() {
return (StringBuffer('GeoPointsCompanion(')
..write('id: $id, ')
..write('name: $name, ')
..write('latitude: $latitude, ')
..write('longitude: $longitude')
..write(')'))
.toString();
}
}
class $RoutesTable extends i2.Routes with i0.TableInfo<$RoutesTable, i1.Route> {
@override
final i0.GeneratedDatabase attachedDatabase;
final String? _alias;
$RoutesTable(this.attachedDatabase, [this._alias]);
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
@override
late final i0.GeneratedColumn<int> id = i0.GeneratedColumn<int>(
'id',
aliasedName,
false,
hasAutoIncrement: true,
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
'PRIMARY KEY AUTOINCREMENT',
),
);
static const i0.VerificationMeta _nameMeta = const i0.VerificationMeta(
'name',
);
@override
late final i0.GeneratedColumn<String> name = i0.GeneratedColumn<String>(
'name',
aliasedName,
false,
type: i0.DriftSqlType.string,
requiredDuringInsert: true,
);
static const i0.VerificationMeta _startMeta = const i0.VerificationMeta(
'start',
);
@override
late final i0.GeneratedColumn<int> start = i0.GeneratedColumn<int>(
'start',
aliasedName,
false,
type: i0.DriftSqlType.int,
requiredDuringInsert: true,
);
static const i0.VerificationMeta _destinationMeta = const i0.VerificationMeta(
'destination',
);
@override
late final i0.GeneratedColumn<int> destination = i0.GeneratedColumn<int>(
'destination',
aliasedName,
false,
type: i0.DriftSqlType.int,
requiredDuringInsert: true,
);
@override
List<i0.GeneratedColumn> get $columns => [id, name, start, destination];
@override
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => $name;
static const String $name = 'routes';
@override
i0.VerificationContext validateIntegrity(
i0.Insertable<i1.Route> instance, {
bool isInserting = false,
}) {
final context = i0.VerificationContext();
final data = instance.toColumns(true);
if (data.containsKey('id')) {
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
}
if (data.containsKey('name')) {
context.handle(
_nameMeta,
name.isAcceptableOrUnknown(data['name']!, _nameMeta),
);
} else if (isInserting) {
context.missing(_nameMeta);
}
if (data.containsKey('start')) {
context.handle(
_startMeta,
start.isAcceptableOrUnknown(data['start']!, _startMeta),
);
} else if (isInserting) {
context.missing(_startMeta);
}
if (data.containsKey('destination')) {
context.handle(
_destinationMeta,
destination.isAcceptableOrUnknown(
data['destination']!,
_destinationMeta,
),
);
} else if (isInserting) {
context.missing(_destinationMeta);
}
return context;
}
@override
Set<i0.GeneratedColumn> get $primaryKey => {id};
@override
i1.Route map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return i1.Route(
id: attachedDatabase.typeMapping.read(
i0.DriftSqlType.int,
data['${effectivePrefix}id'],
)!,
name: attachedDatabase.typeMapping.read(
i0.DriftSqlType.string,
data['${effectivePrefix}name'],
)!,
start: attachedDatabase.typeMapping.read(
i0.DriftSqlType.int,
data['${effectivePrefix}start'],
)!,
destination: attachedDatabase.typeMapping.read(
i0.DriftSqlType.int,
data['${effectivePrefix}destination'],
)!,
);
}
@override
$RoutesTable createAlias(String alias) {
return $RoutesTable(attachedDatabase, alias);
}
}
class Route extends i0.DataClass implements i0.Insertable<i1.Route> {
final int id;
final String name;
final int start;
final int destination;
const Route({
required this.id,
required this.name,
required this.start,
required this.destination,
});
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
map['id'] = i0.Variable<int>(id);
map['name'] = i0.Variable<String>(name);
map['start'] = i0.Variable<int>(start);
map['destination'] = i0.Variable<int>(destination);
return map;
}
i1.RoutesCompanion toCompanion(bool nullToAbsent) {
return i1.RoutesCompanion(
id: i0.Value(id),
name: i0.Value(name),
start: i0.Value(start),
destination: i0.Value(destination),
);
}
factory Route.fromJson(
Map<String, dynamic> json, {
i0.ValueSerializer? serializer,
}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return Route(
id: serializer.fromJson<int>(json['id']),
name: serializer.fromJson<String>(json['name']),
start: serializer.fromJson<int>(json['start']),
destination: serializer.fromJson<int>(json['destination']),
);
}
@override
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'id': serializer.toJson<int>(id),
'name': serializer.toJson<String>(name),
'start': serializer.toJson<int>(start),
'destination': serializer.toJson<int>(destination),
};
}
i1.Route copyWith({int? id, String? name, int? start, int? destination}) =>
i1.Route(
id: id ?? this.id,
name: name ?? this.name,
start: start ?? this.start,
destination: destination ?? this.destination,
);
Route copyWithCompanion(i1.RoutesCompanion data) {
return Route(
id: data.id.present ? data.id.value : this.id,
name: data.name.present ? data.name.value : this.name,
start: data.start.present ? data.start.value : this.start,
destination: data.destination.present
? data.destination.value
: this.destination,
);
}
@override
String toString() {
return (StringBuffer('Route(')
..write('id: $id, ')
..write('name: $name, ')
..write('start: $start, ')
..write('destination: $destination')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(id, name, start, destination);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is i1.Route &&
other.id == this.id &&
other.name == this.name &&
other.start == this.start &&
other.destination == this.destination);
}
class RoutesCompanion extends i0.UpdateCompanion<i1.Route> {
final i0.Value<int> id;
final i0.Value<String> name;
final i0.Value<int> start;
final i0.Value<int> destination;
const RoutesCompanion({
this.id = const i0.Value.absent(),
this.name = const i0.Value.absent(),
this.start = const i0.Value.absent(),
this.destination = const i0.Value.absent(),
});
RoutesCompanion.insert({
this.id = const i0.Value.absent(),
required String name,
required int start,
required int destination,
}) : name = i0.Value(name),
start = i0.Value(start),
destination = i0.Value(destination);
static i0.Insertable<i1.Route> custom({
i0.Expression<int>? id,
i0.Expression<String>? name,
i0.Expression<int>? start,
i0.Expression<int>? destination,
}) {
return i0.RawValuesInsertable({
if (id != null) 'id': id,
if (name != null) 'name': name,
if (start != null) 'start': start,
if (destination != null) 'destination': destination,
});
}
i1.RoutesCompanion copyWith({
i0.Value<int>? id,
i0.Value<String>? name,
i0.Value<int>? start,
i0.Value<int>? destination,
}) {
return i1.RoutesCompanion(
id: id ?? this.id,
name: name ?? this.name,
start: start ?? this.start,
destination: destination ?? this.destination,
);
}
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
if (id.present) {
map['id'] = i0.Variable<int>(id.value);
}
if (name.present) {
map['name'] = i0.Variable<String>(name.value);
}
if (start.present) {
map['start'] = i0.Variable<int>(start.value);
}
if (destination.present) {
map['destination'] = i0.Variable<int>(destination.value);
}
return map;
}
@override
String toString() {
return (StringBuffer('RoutesCompanion(')
..write('id: $id, ')
..write('name: $name, ')
..write('start: $start, ')
..write('destination: $destination')
..write(')'))
.toString();
}
}
+12 -11
View File
@@ -11,17 +11,17 @@
/// Admonition flavours
$admonitions: (
"note": pencil-circle $clr-blue-a200,
"abstract": clipboard-text $clr-light-blue-a400,
"info": information $clr-cyan-a700,
//"abstract": clipboard-text $clr-light-blue-a400,
//"info": information $clr-cyan-a700,
"tip": fire $clr-teal-a700,
"success": check $clr-green-a700,
"question": help-circle $clr-light-green-a700,
"warning": alert $clr-orange-a400,
"failure": close $clr-red-a200,
"danger": lightning-bolt-circle $clr-red-a400,
"bug": shield-bug $clr-pink-a400,
"example": test-tube $clr-deep-purple-a200,
"quote": format-quote-close $clr-grey
"success": check $clr-green-a700
//"question": help-circle $clr-light-green-a700,
//"warning": alert $clr-orange-a400,
//"failure": close $clr-red-a200,
//"danger": lightning-bolt-circle $clr-red-a400,
//"bug": shield-bug $clr-pink-a400,
//"example": test-tube $clr-deep-purple-a200,
//"quote": format-quote-close $clr-grey
) !default;
// ----------------------------------------------------------------------------
@@ -45,7 +45,7 @@ $admonitions: (
display: flow-root;
line-height: 1.35rem;
padding: 0 px2rem(12px);
margin: px2em(20px, 12.8px) 0;
margin: px2rem(20px) px2rem(12.8px);
font-size: px2rem(12.8px);
background-color: var(--background-card);
border: px2rem(1.5px) solid $clr-blue-a200;
@@ -94,6 +94,7 @@ $admonitions: (
// Adjust spacing on last child
html & > :last-child {
margin-top: px2rem(12px);
margin-bottom: px2rem(12px);
}
}
+2 -1
View File
@@ -1,5 +1,6 @@
// https://github.com/squidfunk/mkdocs-material/blob/c68fac7fb3071fa4f45cc823e2ca2ea82fd67b43/src/templates/assets/stylesheets/main/extensions/pymdownx/_details.scss#L4
@use "constants" as *;
@use "admonition";
// Details
@@ -65,7 +66,7 @@
height: px2rem(20px);
content: "";
background-color: currentcolor;
mask-image: var(--md-details-icon);
mask-image: url("/images/chevron-right.svg");
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
+1
View File
@@ -25,6 +25,7 @@ dependencies:
rxdart: ^0.28.0
jaspr_content_snippets: ^0.1.1
glob: ^2.1.3
markdown: ^7.3.0
dev_dependencies:
build_runner: ^2.6.0
+49
View File
@@ -0,0 +1,49 @@
import 'package:drift_website/src/common.dart';
import 'package:markdown/markdown.dart';
import 'package:test/test.dart';
void main() {
test('parses admonitions', () {
final docs = driftMarkdownDocumentBuilder();
final parsed = docs.parse('''
!!! note
Content
''');
expect(renderToHtml(parsed), '''
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Content</p>
</div>''');
});
test('can set a custom title', () {
final docs = driftMarkdownDocumentBuilder();
final parsed = docs.parse('''
!!! tip "Custom title"
Content
''');
expect(renderToHtml(parsed), '''
<div class="admonition tip">
<p class="admonition-title">Custom title</p>
<p>Content</p>
</div>''');
});
test('can generate collapsible', () {
final docs = driftMarkdownDocumentBuilder();
final parsed = docs.parse('''
??? note
Content
''');
expect(renderToHtml(parsed), '''
<details class="note"><summary>Note</summary>
<p>Content</p>
</details>''');
});
}
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21 7 9 19l-5.5-5.5 1.41-1.41L9 16.17 19.59 5.59z"/></svg>

After

Width:  |  Height:  |  Size: 127 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6z"/></svg>

After

Width:  |  Height:  |  Size: 122 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17.66 11.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33 7.26 13 4.85 13.95 3c-.95.23-1.78.75-2.49 1.32-2.59 2.08-3.61 5.75-2.39 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.23.1-.47.04-.66-.12a.6.6 0 0 1-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78 10 4.87 12.3 5 14.47c.06.5.12 1 .29 1.5.14.6.41 1.2.71 1.73 1.08 1.73 2.95 2.97 4.96 3.22 2.14.27 4.43-.12 6.07-1.6 1.83-1.66 2.47-4.32 1.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16 6.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82 1.19-.28 1.9-1.16 2.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63 1.06.77 1 1.98 1.44 2.24 2.8.04.14.06.28.06.43.03.82-.33 1.72-.93 2.27"/></svg>

After

Width:  |  Height:  |  Size: 729 B