Hayagriva

repository·main·Indexed 20 days ago

https://github.com/typst/hayagriva

A Rust-based bibliography management tool for literature database management, storage, and citation formatting. It supports reading and writing YAML and BibTeX, formatting citations using CSL styles, and querying entries via a custom selector language. Available as both a command-line interface (CLI) and a Rust library.

Tokens
20.4K
Snippets
70
Records
93
Agent score
72%

What's inside hayagriva

  1. Format strings with case control and math

    main

    Hayagriva uses Formattable Strings which can be transformed by citation styles (e.g., case folding).

    Case Control

    • Default: Strings may be case-folded by the style.
    • Partial Preservation: Use braces {} to protect specific parts. Wrap the whole string in quotes.
    • Verbatim: To disable all formatting and preserve exact casing, use the value sub-field with verbatim: true.

    Math and Short Forms

    • Math: Wrap Typst mathematical markup in $.
    • Short Forms: Provide a short sub-field for citation styles to use instead of the full value.

    Note: Title and sentence case folding are automatically disabled if the language key is set to something other than English.

    # Case folding
    publisher: UN World Food Programme
    
    # Partial preservation
    publisher: "{imagiNary} Publishing"
    
    # Verbatim (no formatting)
    publisher:
        value: UN World Food Programme
        verbatim: true
    
    # Short forms
    journal:
        value: International Proceedings of Customs
        short: Int. Proc. Customs
  2. Represent publication hierarchies using parents

    main

    To avoid field bloat, Hayagriva uses the concept of parents. Instead of having many different title fields for an article, its journal, and its series, you nest the information using the parent field.

    • Single Parent: Use the parent key followed by the fields of the containing media. Every field available to a top-level item is also available to its parents.
    • Multiple Parents: If an item is published in multiple ways (e.g., a conference talk that is also a video), parent can be an array of mappings.
    • Nested Parents: Parents can have their own parent fields, allowing for deep hierarchies (e.g., an Artwork inside an Anthology).
    • Default Parent Type: If a type is not specified for a parent, it uses a default parent type based on the entry type.
    # Single parent example
    kinetics:
        type: Article
        title: Kinetics and luminescence...
        parent:
            type: Periodical
            title: Physical Review B
            volume: 102
    
    # Multiple parents example
    wwdc-network:
        type: Article
        title: Boost Performance...
        parent:
            - type: Conference
              title: World Wide Developer Conference 2020
            - type: Video
              url: https://developer.apple.com/videos/...
    
    # Nested parents example
    plaque:
        type: Misc
        parent:
            type: Artwork
            parent:
                type: Anthology
                title: Bleibtreustraße
  3. Use Timestamps and Timestamp Ranges

    main

    Timestamps represent specific points in media. They follow the format DD:HH:MM:SS,msms (where msms is milliseconds). Most parts can be omitted, but MM:SS is the minimum.

    Important: Always wrap timestamp strings in double-quotes because they contain colons.

    Timestamp Range: A string containing two timestamps separated by a hyphen (START-END).

    # Single timestamp
    runtime: "01:42:21,802"
    
    # Range
    time-range: "03:35:21-03:58:46"
  4. Filter bibliographies using Selectors

    main

    Hayagriva uses a custom selector language to filter media types and metadata.

    In Rust

    You can use the select! macro for constant selectors to avoid runtime parsing costs, or Selector::parse for dynamic ones. Use Selector::matches for a boolean check, or Selector::apply if you need to access bound data from parent entries.

    In CLI

    Use the --select flag to filter entries. For example, to find entries with a URL or DOI: hayagriva literature.yaml --select "*[url] | *[doi]" reference

    use hayagriva::select;
    
    let journal = select!((Article["date"]) > ("journal":Periodical));
    assert!(journal.matches(entry));
  5. Understand the Hayagriva YAML file format structure

    main

    A Hayagriva file is a YAML document containing a single mapping of mappings. Each literature item is identified by a unique key (the name of the item) followed by its fields (properties describing the item).

    Key characteristics:

    • Keys: Must come first, followed by a colon (e.g., harry:).
    • Fields: Indented under the key, consisting of a field name, a colon, and a value (e.g., title: Harry Potter).
    • Arrays: Used for fields with multiple values (like author). You can use the compact syntax [item1, item2] (wrap names in double-quotes if they contain commas) or the verbose bulleted list syntax.
    • Composite Data: Some fields accept complex objects. For example, a url can include both a value and a date using either nested mapping or JSON-style compact syntax.
    # Basic item structure
    item-key:
        type: Book
        title: Example Title
        author: ["Name, First", "Name, Second"]
    
    # Composite data example
    url: { value: http://example.com, date: 2020-11-30 }
  6. Understand Hayagriva Entry Types

    main

    The type field (case-insensitive) defines the media type of an entry and often determines its default parent. If no type is provided, it defaults to misc or the default parent of its containing entry.

    Common Entry Types:

    • article: Short text in a greater publication (default parent: periodical).
    • chapter: Section of a greater work (default parent: book).
    • entry: Short segment of media (default parent: reference).
    • anthos: Text in an Anthology (default parent: anthology).
    • report: Document compiled by authors (often affiliated to an organization).
    • thesis: Scholarly work for a degree.
    • web: Native internet content (e.g., web app). For blog articles, use article with a blog parent.
    • scene: Part of a show/performed media (default parent: video).
    • artwork: Artistic/creative expression (default parent: exhibition).
    • patent: Technical document for an invention.
    • case: Legal case reference.
    • newspaper: Newspaper issue.
    • legislation: Legal document/draft (default parent: anthology).
    • manuscript: Candidate for publication.
    • original: Original container before re-publication.
    • post: Micro-blogging post (default parent: post).
    • misc: Unmatched items.
    • performance: Live artistic performance.
    • periodical: Periodic publication (journals, magazines).
    • proceedings: Official record of conference events.
    • book: Long-form physical work.
    • blog: Set of self-published articles.
    • reference: Work of reference (manual, dictionary).
    • conference: Professional conference (implies the event itself; use article with proceedings parent for papers).
    • anthology: Collection of texts on a theme.
    • repository: Public source code/data storage.
    • thread: Internet discussion.
    • video: Motion picture (default parent: video).
    • audio: Recorded sound (default parent: audio).
    • exhibition: Curated set of artworks.
  7. Define a Person in Hayagriva

    main

    A person can be defined as a simple string or a structured object.

    String Format

    Use the format [Prefix] Lastname, [Suffix], Givenname. The parser automatically identifies the prefix by looking for consecutive lowercase words at the start.

    • Doe, Janet
    • Luther King, Jr., Martin
    • von der Leyen, Ursula

    Structured Format

    Use sub-fields for more control, especially if names contain commas or require an alias:

    • name (required)
    • given-name
    • prefix
    • suffix
    • alias
    # Simple string
    author: "Doe, Janet"
    
    # Structured
    author:
        given-name: Gloria Jean
        name: Watkins
        alias: bell hooks
  8. Use Hayagriva as a Rust library

    main

    Hayagriva can be integrated into Rust applications to parse bibliographies and format citations using CSL (Citation Style Language) styles.

    Parsing YAML

    Use hayagriva::io::from_yaml_str to parse a YAML string into a bibliography.

    Formatting Citations

    To format citations, you must:

    1. Load a CSL style (e.g., using IndependentStyle::from_xml).
    2. Load locale files (e.g., using LocaleFile::from_xml).
    3. Create a BibliographyDriver.
    4. Wrap entries in CitationItems and pass them to the driver via CitationRequest.
    5. Call driver.finish() with a BibliographyRequest to get the results.
    use hayagriva::io::from_yaml_str;
    use hayagriva::{BibliographyDriver, BibliographyRequest, BufWriteFormat, CitationItem, CitationRequest};
    use hayagriva::citationberg::{LocaleFile, IndependentStyle};
    
    // 1. Parse bibliography
    let bib = from_yaml_str(yaml_content).unwrap();
    
    // 2. Setup driver and style
    let mut driver = BibliographyDriver::new();
    let style = IndependentStyle::from_xml(&style_xml).unwrap();
    let locales = [LocaleFile::from_xml(&locale_xml).unwrap().into()];
    
    // 3. Request citations
    for entry in bib.iter() { 
        let items = vec![CitationItem::with_entry(entry)];
        driver.citation(CitationRequest::from_items(items, &style, &locales));
    }
    
    // 4. Finalize
    let result = driver.finish(BibliographyRequest {
        style: &style,
        locale: None,
        locale_files: &locales,
    });
  9. Understand IbidState in citations

    main

    The IbidState enum determines how a citation relates to the previous one, which is critical for styles that use 'ibid' or similar markers.

    • Ibid: The current citation is exactly the same as the previous one (same entry and same locator).
    • IbidWithLocator: The current citation references the same entry as the previous one, but with a different locator.
    • Different: The current citation references a different entry, or the previous citation had a locator while this one does not.
  10. Filter entries using the Selector language

    main

    Hayagriva provides a custom selector language to filter bibliographic entries by type or field. You can use the select! macro for constant selectors to avoid runtime parsing costs, or Selector::parse for dynamic strings.

    Use Selector::matches to check if an entry meets a criteria, or Selector::apply to retrieve bound data from parent entries.

    use hayagriva::select;
    use hayagriva::io::from_yaml_str;
    
    let yaml = r#"
    quantized-vortex:
        type: Article
        author: Gross, E. P.
        title: Structure of a Quantized Vortex in Boson Systems
        date: 1961-05
        page-range: 454-477
        serial-number:
            doi: 10.1007/BF02731494
        parent:
            issue: 3
            volume: 20
            title: Il Nuovo Cimento
    "#;
    
    let entries = from_yaml_str(yaml).unwrap();
    // Using the select! macro
    let journal = select!((Article["date"]) > ("journal":Periodical));
    assert!(journal.matches(entries.nth(0).unwrap()));
  11. Understand DisambiguatedNameForm variants

    main

    The DisambiguatedNameForm enum defines the different ways a person's name can be rendered during CSL (Citation Style Language) disambiguation. These forms control the level of detail provided for a name:

    • Count: Only the number of names is rendered.
    • ShortInitialized: Only the family name is printed, with initials used for the first name (if initialization is available).
    • ShortFull: Only the family name is printed, without initials.
    • LongInitialized: The name is printed with a first name initial.
    • LongFull: The full name is printed.

    You can check if a form is considered 'long' using the is_long() method, which returns true for LongFull or LongInitialized.

    /// Count the names.
    /// Print only the family name. Initialization is available.
    /// Print only the family name. Initialization is unavailable.
    /// Print the name with a first name initial.
    /// Print the full name.
    pub enum DisambiguatedNameForm {
        Count,
        ShortInitialized,
        ShortFull,
        LongInitialized,
        LongFull,
    }