Skip to content

Commit

Permalink
Implement CSS Grid (#205)
Browse files Browse the repository at this point in the history
* Add style-properties.md doc

* Add f32_max and f32_min functions to sys module

* Add Grid variant to Display enum

* Group FlexboxLayout properties by logical group

* Add CSS Grid track definition properties

* Add CSS Grid placement properties

* WIP Grid data structures

* Use separate enums for MinTrackSizingFunction and MaxTrackSizingFunction

* More WIP Grid data structures

* Update grid size estimates to resolve spans against the implicit grid estimates

* Expand GridOccupancyMatrix when recording the positions of out of bounds grid items

* Implement remainder of grid auto placement

* Improve no_std/alloc compatibility

* Make placement functions return placement spans rather than recording placement directly

* Fix grid size estimation with negative coords + add tests for grid size estimation

* Cargo fmt + comment updates

* Add auto placement test + many auto placement fixes

* Refactor placement test into a reusable test runner

* Add test for definitely positioned items

* Add placement test for column auto flow

* Fix placement of oversized items + add test

* Fix placement with secondary axis fixed + add test

* Remove commented code to break infinite loop

* Add test for dense packing algorithm

* Add test for sparse packing algorithm

* Fix alloc compatibility

* Add comments main grid compute function

* Add test for initialize_grid_tracks + fixes

* Track sizing algorithm WIP

* Fix style.rs tests

* Move grid module to be a submodule of the  compute module

* Track sizing algo exploration

* Reintroduce planned increase variables

* Track sizing WIP

* Factor common alignment logic into a function

* Fix test generator to use correct name for TrackSizingFunction

* Fix overzealous assertion in coordinate transformation code

* Implement naive track sizing and alignment for fixed sized tracks

* Grid: Add tests to cover fixed tracks/no free space case

* Merge AlignContent with JustifyContent

- Remove Default impl for the new type
- Make style props take Option<AlignContent> rather than AlignContent

* Test generator: add support for missing alignment/justify values

* Add tests for grid track alignment

* Merge AlignItems with AlignSelf. AlignSelf::Auto become Option::None

* Make AlignItems optional. Remove align_self method from Style struct

* Add justify_items and justify_self style properties

* Rename FlexStart and FlexEnd alignment variants to Start and End

* Implement item alignment for fixed sized and stretched grid items

* Fix grid-{row,columns}-{start,end} support in generated tests

* Fix sizing of fixed size items with stretch alignment

* Add tests for grid item alignment

* Add known size font + support for calculating content sizes to gentest JS script

* Add MeasureFunc support to gentest script

* Add support for content-sizing grid children

* Add basic test for content-sized grid children

* Gentest: fix generation of minmax() track sizing functions

* Implement 11.6 "Maximise Tracks"

* Add tests for fixed minmax() columns

* Implement 11.8 "Stretch auto Tracks"

* Add test for auto tracks

* Treat text fixtures beginning with x as disabled tests

* Implement 11.7. Expand Flexible Tracks

* Add tests for basic fr expansion cases

* Resolve container size before performing alignment

* Implement Step 3.1 "intrinsic minimums" of 11.5 "Resolve Intrinsic Track Sizes"

* Add tests for content sizing auto tracks

* Add commented out second run through track sizing

* Implement Step 3.2 "min/max-content" of 11.5. "Resolve Intrinsic Track Sizes"

* Add test for content-sizing a min-content column

* Move spanned track limit computation to method on GridItem

* Implement Step 3.3 "max-content minimums" of 11.5. "Resolve Intrinsic Track Sizes"

* Add test for max-content minimums

* De-deduplicate distribute space up to limits logic

* Implement Step 3.5 "max-content maximums" of 11.5. "Resolve Intrinsic Track Sizes"

* Implement Step 3.4 "floor growth limit at base size" of 11.5. "Resolve Intrinsic Track Sizes"

* Add test for content sized intrinsic max track sizing function column

* Implement Step 3.6 "max-content maximums" of 11.5. "Resolve Intrinsic Track Sizes"

* Add test for max-content max track sizing function column

* Use planned_growth_limit_increase

* Rename grid_fr_auto test to make name more unique

* Add test for item that spans a min-content and flexible column

* Pass correct to distribution function for max-content distribution

* Fixes for sizing items crossing flex tracks
Only distribute space from items crossing flex tracks to flex tracks

* Add tests for flex tracks

* Fix typo when passing inherent size for final placement

* Add test where content sized width determines size of fr, but item doesn't end up spanning the entire width of the track

* Reorganise grid module

* Remove commented out code

* Document grid style items

* Remove track sizing debug logs

* Remove track_sizing_algorithm_inner indirection

* Extract 11.7 expand flexible tracks into it's own method

* Extract 11.8 stretch auto tracks into it's own function

* Extract 11.6 maximise tracks into it's own function

* Extract 11.4. Initialize track sizes into it's own function

* Split 11.5. resolve intrinsic track sizes into it's own function

* Co-locate function for sub-steps with the main step function

* Remove unused AvailableSpaceMode enum (this is now implemented using a closure)

* Improve top level grid algorithm comments

* Remove AvailableSpaceCache and uses

* Remove unused populate_negative_grid_tracks function

* Move item positioning logic to alignment module

* Remove unused imports

* Add grid styles to prelude

* Remove unused parameters in flexbox module

* Remove measure_node parameter from track_sizing_function

* Remove unused TrackCounts code

* Fix grid_item warnings

* Remove GridAxisTracks struct

* Clear up warnings in track_sizing module

* Fix warnings in grid_track module

* Document absolute axis get functions

* Remove unused methods on CellOccupancyMatrix struct

* Disable unused code warning for gutter alignment adjustment code

* Remove 'static from generated measure funcs (clippy)

* Remove unncessary spread defaults from generated tests (clippy)

* Selected clippy auto-fixes

* Pass immutable reference instead of mutable reference

* Convert gentest script from json crate to serde_json

* Fix clippy lints in gentest script

* Add module documentation

* Resolve clippy lints in style module

* Document grid axis module

* Rename GridAxis to AbstractAxis

* Move axis module to top level of crate

* Allow coordinate conversion function to be unused

* Fix lints in placement module

* Document coordinate transformation code

* Document grid item module

* Document track sizing module

* Fix clippy lints in alignment module

* Fix clippy lints in grid_track module

* Document the explicit_grid module

* Document the cell_occupancy module

* Remove unused grid_axis_sum method

* Convert track sizing functions to use LengthPercentage instead of Dimension

* Remove unnecessary .into() calls

* Split style module into multiple files

* Implement content alignment adjustment for track sizing algorithm

* Don't distribute maximum's space to growth limits for items crossing flex tracks

* Implement FromPoints, TaffyZero, and TaffyAuto for track sizing functions

* Hide grid implementation behind a feature flag 'experimental_grid'

* Rename estimate_size module to implicit_grid

* Convert TrackSizingFunction to MinMax struct + implement style helpers

Style helpers:
- percent
- min_content
- max_content
- flex
- minmax

* Rename Dimension method get_absolute to into_option

* Add support for repeat(auto-fill)

* Add repeat(auto-fill) test for container with padding

* Add support for repeat() track definitions to gentest script

* Add simple generated test for repeat(auto-fill)

* Move AvailableSpace to style module + implement style helpers for AvailableSpace

* Rename as_options() method on Size<AvailableSpace> to into_options()

* Collapse first and last tracks of the implicit grid

* Add support for repeat(auto-fit)

* Add support for fit-content() with pixel/points argument values

* Fix typo in src/style/grid.rs

Co-authored-by: Alice Cecile <[email protected]>

* Add backticks src/style/grid.rs

Co-authored-by: Alice Cecile <[email protected]>

* Fix typo in src/style/grid.rs

Co-authored-by: Alice Cecile <[email protected]>

* Add backticks in src/style/grid.rs

Co-authored-by: Alice Cecile <[email protected]>

* Update style-properties.md

* Add line breaks to doc comment in src/style/grid.rs

Co-authored-by: Alice Cecile <[email protected]>

* Document style helpers

* Remove doc string from impl

* Remove multiple blank lines

* Fix track alignment for grid containers with padding and/or borders

* Fix list blanks lines

* Add cargo alias for generating tests

* Exclude hermit-abi from duplicate dependency detection

* Gitignore file names ending in -test-names.txt

* Fix application of max-sizes to leaf nodes

* Implement positioning for hidden/absolute grid items + perform recursive layout on all grid items

* Add gentests for absolutely positioned grid children

* Add test for hidden grid children

* Add support for children with margins (fixed sized columns)

* Add gentests for children with margins (fixed size columns)

* Take margins into account when content sizing tracks

* Add tests for intrinsically sized tracks containing children with margins

* Pass stretch fit size as a known_dimension when laying out grid children

* Use MaybeMath helpers in grid alignment

* Fix running tests without experimental_grid feature

* Don't enable experimental_grid feature by default for tests/examples

* Allow test measure_func to be unused (depends on feature flags)

* Run tests with and without experimental_grid feature in CI

* Fix CSS Grid CI jobs

* Add alignment style changes to release notes

* Add style helpers for grid placement properties

* Add grid_holy_grail example

* Rename GridPlacement::Track to GridPlacement::Line

* CSS Grid release notes WIP

* Add supported properties to release notes

* Fix table links

* More release note rendering fixes

* Split missing features in planned/not planned

* Add links to CSS Grid learning resources

* Link to grid example in release notes rather than including it inline

* Bump header sizes

* Add AvailableSpace module change to release notes

* Improve documentation of grid styles

* Fix benchmark compilation (failed due to Style no longer being Copy)

* Update CONTRIBUTING guide to use cargo gentest

* Rename CI tasks to stop github getting confused

* Iterate over grid items and absolute/hidden children separately when performing final positioning

* Fix typo where negative_implicit count was used to generate positive_implicit tracks

* Add tests for out of flow items and positive implicit items

* Improve debug tree printing (include node key + align output)

* Remove completed TODO

* Fix placement for items with a definite primary axis and indefinite secondary axis position

* Add out of order items and implicit tracks tests

* Enabled grid feature when running clippy in CI

* Fix clippy lints with grid feature enabled

Co-authored-by: Alice Cecile <[email protected]>
  • Loading branch information
nicoburns and alice-i-cecile authored Dec 22, 2022
1 parent 4658ee0 commit 6fd2c6b
Show file tree
Hide file tree
Showing 915 changed files with 30,226 additions and 13,565 deletions.
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[alias]
gentest = "run --package gentest --"
32 changes: 31 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,36 @@ jobs:
command: test
args: --no-default-features --features alloc

test-features-default-with-grid:
name: "Test Suite [Features: default + experimental_grid]"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions-rs/cargo@v1
with:
command: test
args: --features experimental_grid

test-features-alloc-with-grid:
name: "Test Suite [Features: alloc + experimental_grid]"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions-rs/cargo@v1
with:
command: test
args: --no-default-features --features alloc,experimental_grid

fmt:
name: Rustfmt
runs-on: ubuntu-latest
Expand Down Expand Up @@ -82,7 +112,7 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: clippy
args: --workspace -- -D warnings
args: --workspace --features experimental_grid -- -D warnings

markdownlint:
name: Markdown Lint
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ Cargo.lock
.DS_Store

.vscode

*-test-names.txt
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ If you are Ubuntu, you will have to install `openssl` first,
and then can follow [these instructions](https://tecadmin.net/setup-selenium-chromedriver-on-ubuntu/).
Be sure that your Chrome vesion matches the downloaded `chromedriver` version!

Once you have chromedriver installed and available in `PATH` you can re-generate all tests by running `cargo run --package gentest`. You should not manually update the tests in `tests/generated`. Instead, fix the script in `scripts/gentest/` and re-generate them. This can happen after a refactor. It can be helpful to commit the updated tests in a dedicated commit so that they can be easier to ignore during review.
Once you have chromedriver installed and available in `PATH` you can re-generate all tests by running `cargo gentest`. You should not manually update the tests in `tests/generated`. Instead, fix the script in `scripts/gentest/` and re-generate them. This can happen after a refactor. It can be helpful to commit the updated tests in a dedicated commit so that they can be easier to ignore during review.

To add a new test case add another HTML file to `/test_fixtures` following the current tests as a template for new tests.

Expand Down
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ num-traits = { version = "0.2", default-features = false }
rand = { version = "0.8.5", optional = true }
serde = { version = "1.0", optional = true, features = ["serde_derive"] }
slotmap = "1.0.6"
grid = { version = "0.7.0", optional = true }

[features]
default = ["std"]
experimental_grid = ["dep:grid"]
alloc = []
std = ["num-traits/std"]
serde = ["dep:serde"]
Expand Down
147 changes: 146 additions & 1 deletion RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,161 @@
# Release Notes

## 0.3.0 (Unreleased)
## 0.3.0-alpha1 (Unreleased)

This is the first in a series of planned alpha releases to allow users of Taffy to try out the new CSS Grid layout mode in advance of a stable release. We hope that by marking this is alpha release we are clearly communicating that this a pre-release and that the implementation is not yet of production quality. But we never-the-less encourage you to try it out. Feedback is welcome, and bug reports for the Grid implementation are being accepted as of this release.

**Note: CSS Grid support must be enabled using the `experimental_grid` feature. For the time being this feature is not enabled by default.**

### New Feature: CSS Grid (Experimental)

We very excited to report that we have an initial version of the CSS Grid layout available. This is in addition to the existing Flexbox layout support, and the two modes interoperate (although this interaction has not been extensively tested). You can set a node to use Grid layout by setting the `display` property to `Display::Grid`.

#### Learning Resources

Taffy implements the CSS Grid specification faithfully, so documentation designed for the web should translate cleanly to Taffy's implementation. If you are interested in learning how to use CSS Grid, we would recommend the following resources:

- [CSS Grid Garden](https://cssgridgarden.com/). This is an interactive tutorial/game that allows you to learn the essential parts of CSS Grid in a fun engaging way.
- [A Complete Guide To CSS Grid](https://css-tricks.com/snippets/css/complete-guide-grid/) by CSS Tricks. This is detailed guide with illustrations and comphrehensive written explanation of the different Grid propertie and how they work.

#### Supported Features & Properties

In addition to the usual sizing/spacing proerties (size, min_size, padding, margin, etc), the following Grid style properties are supported on Grid Containers:

| Property | Explanation |
| --- | --- |
| [`grid-template-columns`] | The track sizing functions of the grid's explicit columns |
| [`grid-template-rows`] | The track sizing functions of the grid's explicit rows |
| [`grid-template-areas`] | Defines named grid areas |
| [`grid-auto-rows`] | Track sizing functions for the grid's implicitly generated rows |
| [`grid-auto-columns`] | Track sizing functions for the grid's implicitly generated columns |
| [`grid-auto-flow`] | Whether auto-placed items are placed row-wise or column-wise. And sparsely or densely. |
| [`gap`] | The size of the vertical and horizontal gaps between grid rows/columns |
| [`align-content`] | Align grid tracks within the container in the inline (horizontal) axis |
| [`justify-content`] | Align grid tracks within the container in the block (vertical) axis |
| [`align-items`] | Align the child items within their grid areas in the inline (horizontal) axis |
| [`justify-items`] | Align the child items within their grid areas in the block (vertical) axis |

And the following Grid style properties are supported on Grid Items (children):

| Property | Explanation |
| --- | --- |
| [`grid-row`] | The (row) grid line the item starts at (or a span) |
| [`grid-column`] | The (column) grid line the item end at (or a span) |
| [`align-self`] | Align the item within it's grid area in the inline (horizontal) axis. Overrides `align-items`. |
| [`justify-self`] | Align the item within it's grid area in the block (vertical) axis. Overrides `justify-items`. |

[`grid-template-columns`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns
[`grid-template-rows`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-rows
[`grid-template-areas`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-areas
[`grid-auto-rows`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-rows
[`grid-auto-columns`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-columns
[`grid-auto-flow`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow
[`gap`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/gap
[`align-content`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/align_content
[`justify-content`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/justify_content
[`align-items`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/align-items
[`justify-items`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/justify-items
[`grid-row`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/grid-row
[`grid-column`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/grid-column
[`align-self`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/align-self
[`justify-self`]: https:://developer.mozilla.org/en-US/docs/Web/CSS/justify-self

The following properties and features are not yet supported, but are planned for the near future:

- Baseline alignment
- `fit-content()` with a percentage argument.
- `repeat()` with integer repetition (but users of Taffy can just expand these definition manually)

The following properties and features are not supported, and there are no immediate plans to implement them:

- Subgrids
- Named grid lines
- Named areas: `grid-template-areas` and `grid-area`
- `grid-template` or `grid` shorthand

#### Example

See [examples/grid_holy_grail.rs](https://github.com/DioxusLabs/taffy/blob/main/examples/grid_holy_grail.rs) for an example using Taffy to implement the so-called [Holy Grail Layout](https://en.wikipedia.org/wiki/Holy_grail_(web_design)). If you want to run this example, the don't forget the enable the CSS Grid cargo feature:

```bash
cargo run --example grid_holy_grail --features experimental_grid
```

### New Feature: Style Helpers

Ten new helper functions have added to the taffy prelude. These helper functions have short, intuitive names, and have generic return types which allow them to magically return the correct type depending on context. They make defining styles much easier, and means you won't typically need to use types like `Dimension` or `TrackSizingFunction` directly.

For example, instead of:

```rust
let size : Size<Dimension> = Size { width: Dimension::Points(100.0), height: Dimension::Percent(50.0) };
```

you can now write

```rust
let size : Size<Dimension> = Size { width: points(100.0), height: percent(50.0) };
```

And that same helper function will work other types like `LengthPercentage` and `MinTrackSizingFunction` that also have a `Points` variant. There are also generic impl's for `Size<T>`, `Rect<T>` and `Line<T>` which means if your node is the same size in all dimensions you can even write

```rust
let size : Size<Dimension> = points(100.0);
```

The following functions work for `Dimension`, `LengthPercentageAuto`, `LengthPercentage`, `AvailableSpace` and for Grid track sizing functions

- `points(f32)` - Generates a `Points` variant with the specified value
- `zero()` - Generates a `Points` variant with the value `0.0`.

The following functions work for `Dimension`, `LengthPercentageAuto`, `LengthPercentage` and for Grid track sizing functions

- `percent(f32)` - Generates a `Percent` value
- `auto()` - Generates an `Auto` variant

The following functions work for `AvailableSpace` and grid track sizing functions:

- `min_content()` - Generates an `MinContent` variant
- `max_content()` - Generates an `MaxContent` variant

The following functions currently work only for grid track sizing functions:

- `flex(f32)` - Genrates a `Flex` variant with the specified flex fraction
- `fit_content(LengthPercentage)` - Generates a `FitContent` variant with the specified limit. Nest `points` or `percent` inside this function to specified the limit.
- `minmax(MinTrackSizingFunction, MaxTrackSizingFunction)` - Generates a track sizing function with different min and max sizing functions. Nest `points`, `percent`, `auto`, `min_content`, `max_content`, or `flex` to specify the min and max functions.
- `repeat(GridTrackRepetition, Vec<TrackSizingFunction>)` - Genereate an auto-repeating track definition.

### Breaking API changes

#### Changes to alignment style types

- `AlignContent` and `JustifyContent` has been merged.
- `JustifyContent` is now an alias of `AlignContent` and contains the `Stretch` variant.
- This variant will be *ignored* (falling back to `Start`) when applied Flexbox containers. It is valid value for Grid containers.
- `AlignItems` and `AlignSelf` have been merged.
- The `Auto` variant of `AlignSelf` has been removed. You should now use `Option::None` if you wish to specify `AlignSelf::Auto`.
- `AlignSelf` is now an alias of `AlignItems`.
- `JustifyItems` and `JustifySelf` aliases have been added. These properties have no affect on Flexbox containers, but apply to Grid containers.
- `Default` impls have been removed from all alignment types. This is because the correct default varies by property, and the types are now shared between multiple properties. The `Style` struct still has a default for each alignment property, so this is considered unlikely to affect you in practice.

#### Strict style types

- New types `LengthPercentage` and `LengthPercentageAuto` have been added.
- `LengthPercentage` is like `Dimension` but only contains the `Points` and `Percent` variants, which allows us to increase type safety for properties that don't support the `Auto` value.
- `LengthPercentageAuto` is currently identical to `Dimension` but will allow us to expand dimension in future to support values like `MinContent`, `MaxContent` and `FitContent`.
- Some style properties have been updated to use either `LengthPercentage` or `LengthPercentageAuto` instead of `Dimension`. You will need to update your code, but it is recommended that you use the new style helpers (see above) rather than using the new types directly (although you certainly can use them directly if you want to).

#### Changes to `LayoutTree`

- Added generic associated type to `LayoutTree` for a `ChildIter`, an iterator on the children of a given node.
- Changed the `children` method of `LayoutTree` to return the `ChildIter` generic associated type to allow for custom tree storage implementations which do not store the children of a node contiguously.
- Added `child_count` method to `LayoutTree` for querying the number of children of a node. Required because the `children` method now returns an iterator instead of an array.
- Added `is_childless` method to `LayoutTree` for querying whether a node has no children.

#### `AvailableSpace` has been moved

The `AvailableSpace` enum has been moved from the `layout` module to the `style` module. If you are importing it via the prelude then you will unaffected by the change.

### Fixes

- Fix case where column-gap style could be used in place of row-gap style (when using a percentage gap with an indefinite container size)
Expand Down
4 changes: 2 additions & 2 deletions benches/big_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ fn build_yoga_deep_hierarchy(taffy: &mut Taffy, node_count: u32, branching_facto
flex_grow: 1.0,
..Default::default()
};
let mut build_leaf_node = |taffy: &mut Taffy| taffy.new_leaf(style).unwrap();
let mut build_leaf_node = |taffy: &mut Taffy| taffy.new_leaf(style.clone()).unwrap();
let mut build_flex_node =
|taffy: &mut Taffy, children: Vec<Node>| taffy.new_with_children(style, &children).unwrap();
|taffy: &mut Taffy, children: Vec<Node>| taffy.new_with_children(style.clone(), &children).unwrap();

let tree = build_deep_tree(taffy, node_count, branching_factor, &mut build_leaf_node, &mut build_flex_node);

Expand Down
1 change: 1 addition & 0 deletions benches/complex.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use criterion::{criterion_group, criterion_main, Criterion};
use taffy::style_helpers::*;
use taffy::tree::LayoutTree;

fn build_deep_hierarchy(taffy: &mut taffy::node::Taffy) -> taffy::node::Node {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 6fd2c6b

Please sign in to comment.