| Crates.io | htmxology-macros |
| lib.rs | htmxology-macros |
| version | 0.26.1 |
| created_at | 2024-11-12 13:17:57.374495+00 |
| updated_at | 2026-01-21 16:20:23.891515+00 |
| description | Macros for the htmxology crate |
| homepage | |
| repository | https://github.com/ereOn/htmxology.rs |
| max_upload_size | |
| id | 1444920 |
| size | 304,519 |
Procedural macros for the htmxology framework.
This crate follows a consistent organizational pattern for all derive macros to maintain clarity and scalability.
Each derive macro should be organized in its own subdirectory with the following structure:
src/
├── macro_name/
│ ├── mod.rs # Main derive function and exports
│ ├── config.rs # Data structures for parsed configuration
│ ├── codegen.rs # Code generation helpers
│ ├── snapshots/ # Insta snapshot test files
│ └── *.rs # Other supporting modules as needed
├── utils.rs # Shared utilities across all macros
└── lib.rs # Crate entry point
mod.rs - Main Entry Pointderive() functionExample structure:
mod config;
mod codegen;
pub fn derive(input: &mut syn::DeriveInput) -> syn::Result<TokenStream> {
let data = crate::utils::expect_enum(input, "MacroName")?;
let configs = parse_configs(data)?;
generate_implementation(configs)
}
#[cfg(test)]
mod snapshot_tests {
use super::*;
use crate::utils::testing::test_derive;
use insta::assert_snapshot;
fn test_macro_name(input: &str) -> String {
test_derive(input, derive)
}
// ... test cases
}
config.rs - Configuration Structuressyn types into config typesKey principles:
VariantConfig, FieldConfig, FieldRole)From implementations or parsing functions for syn typesClone for flexibilityTokenStream - this module should be pure dataExample:
#[derive(Clone)]
pub struct VariantConfig {
pub ident: Ident,
pub fields: FieldsConfig,
// ... other config
}
impl VariantConfig {
pub fn from_variant(variant: &Variant) -> syn::Result<Self> {
// Parse and validate
}
}
codegen.rs - Code Generation HelpersTokenStream from config structuresKey principles:
&Config types and return TokenStream or syn::Result<TokenStream>generate_pattern, generate_url_format)Example:
/// Generates a match pattern for a variant.
///
/// # Example Output
///
/// ```ignore
/// Self::Variant { field1, field2 }
/// ```
pub fn generate_pattern(config: &VariantConfig) -> TokenStream {
// ...
}
snapshots/ - Test Snapshots.snap file per test case{crate}__{module}__snapshot_tests__{test_name}.snaputils.rs)Common functionality shared across all derive macros:
expect_enum() - Validates input is an enum (not struct/union)testing::test_derive() - Wrapper for snapshot testsWhen adding new shared utilities, consider:
All derive macros must have comprehensive snapshot tests:
unit_variant_get, named_body_param)mod snapshot_tests within mod.rscargo insta review after changes to inspect diffsTest structure:
#[test]
fn descriptive_test_name() {
let input = r#"
enum Example {
#[attribute]
Variant,
}
"#;
assert_snapshot!(test_macro_name(input));
}
Before committing changes:
cargo fmt --allcargo test -p htmxology-macros (all tests must pass)cargo clippy -p htmxology-macros (zero warnings)cargo insta review (verify changes are correct)When refactoring an existing derive macro to follow this pattern:
src/macro_name/src/macro_name/mod.rsconfig.rscodegen.rssnapshots/ subdirectorylib.rscargo testgit diffCritical: When moving snapshots, use git mv or ensure file contents are identical to prevent false regressions.
See src/route/ for a complete example following this pattern.