Refactor inline credit to improve hover messages

finchie
Nov 30, 2025, 6:27 AM
72K45XKDA7R3R4I7ZOMZAA2433VR4SD7C7I5K6PCE6RTYL545GGQC

Dependencies

  • [2] WFWTKCJN Create initial Visual Studio Code extension

Change contents

  • file addition: templates (d--r------)
    [2.53768]
  • file addition: hover (d--r------)
    [0.21]
  • file addition: untracked.html (----------)
    [0.40]
  • file addition: tracked.html (----------)
    [0.40]
    <strong>{{ title }}</strong>
    {{ authors }} • {{ relative_timestamp }}
    <hr />
    <table>
    <tbody>
    <tr>
    <th>{{ change_id_header }}</th>
    <td><code>{{ change_id }}</code></td>
    </tr>
    <tr>
    <th>{{ absolute_timestamp_header }}</th>
    <td>{{ absolute_timestamp }}</td>
    </tr>
    </tbody>
    </table>
    {% if let Some(description) = description %}
    {{ description }}
    {% endif %}
  • edit in extensions/vscode/src/vscode_sys/mod.rs at line 91
    [2.61109]
    [2.61109]
    field_setter! {
    MarkdownString {
    "supportHtml": set_support_html(bool);
    }
    }
  • edit in extensions/vscode/src/lib.rs at line 16
    [2.109259]
    [2.109259]
    // TODO: warn instead of returning an error for non-fatal errors
  • replacement in extensions/vscode/src/lib.rs at line 27
    [2.109466][2.109466:109483]()
    mod decorations;
    [2.109466]
    [2.109483]
    mod inline_credit;
  • replacement in extensions/vscode/src/lib.rs at line 211
    [2.116043][2.116043:116191]()
    let selections = text_editor.get_selections()?;
    decorations::inline_credit::render(env, &program_state, &text_editor, selections)?;
    [2.116043]
    [2.116191]
    inline_credit::render(env, &program_state, &text_editor)?;
  • replacement in extensions/vscode/src/lib.rs at line 233
    [2.116712][2.116712:116839]()
    let selections = event.get_selections()?;
    decorations::inline_credit::render(env, &program_state, &editor, selections)
    [2.116712]
    [2.116839]
    inline_credit::render(env, &program_state, &editor)
  • replacement in extensions/vscode/src/lib.rs at line 302
    [2.118878][2.118878:118947]()
    let decoration_type = decorations::create_decoration_type(env)?;
    [2.118878]
    [2.118947]
    let decoration_type = inline_credit::create_decoration_type(env)?;
  • replacement in extensions/vscode/src/lib.rs at line 310
    [2.119166][2.119166:119331]()
    let selections = active_text_editor.get_selections()?;
    decorations::inline_credit::render(env, &extension_state, &active_text_editor, selections)?;
    [2.119166]
    [2.119331]
    inline_credit::render(env, &extension_state, &active_text_editor)?;
  • file move: decorations (d--r------)inline_credit (d--r------)
    [2.54351]
    [2.122472]
  • replacement in extensions/vscode/src/inline_credit/mod.rs at line 1
    [2.122505][2.122506:122529]()
    use crate::vscode_sys;
    [2.122505]
    [2.122529]
    use camino::Utf8PathBuf;
    use icu_locale::locale;
    use crate::{ExtensionState, vscode_sys};
  • replacement in extensions/vscode/src/inline_credit/mod.rs at line 6
    [2.122530][2.122530:122553]()
    pub mod inline_credit;
    [2.122530]
    [2.122553]
    pub mod hover;
    pub mod line_annotation;
  • edit in extensions/vscode/src/inline_credit/mod.rs at line 25
    [2.123292]
    [2.123292]
    }
    // TODO: different rendering modes? e.g. render only at boundaries between lines, render only on cursors, etc
    pub fn render(
    env: &napi::Env,
    program_state: &ExtensionState,
    editor: &vscode_sys::TextEditor,
    ) -> Result<(), napi::Error> {
    let editor_document = editor.get_document()?;
    let document_uri = editor_document.get_uri()?;
    let Some((repository_path, open_repository)) = program_state
    .repositories
    .get_open_repository(env, &document_uri)?
    else {
    tracing::warn!(
    message = "No repository for URI",
    uri = document_uri.to_string()?
    );
    return Ok(());
    };
    let absolute_file_path = Utf8PathBuf::from(document_uri.get_fs_path()?);
    let relative_file_path =
    absolute_file_path
    .strip_prefix(&repository_path)
    .map_err(|error| {
    napi::Error::from_reason(format!(
    "Failed to strip prefix {repository_path} from {absolute_file_path}: {error}"
    ))
    })?;
    let open_file = open_repository
    .repository
    .get_open_file(relative_file_path)
    .ok_or_else(|| {
    napi::Error::from_reason(format!("unable to get open file for {relative_file_path}"))
    })?;
    // TODO: don't initialize here
    let localization_context = l10n_embed::Context::new(locale!("en-US"), false);
    let mut decoration_options_list = Vec::new();
    for editor_selection in editor.get_selections()? {
    let start_line = editor_selection.get_start()?.get_line()?;
    let end_line: u32 = editor_selection.get_end()?.get_line()?;
    let selected_range = (start_line as usize)..=(end_line as usize);
    let credits = open_file.credit(selected_range);
    for credit_span in credits {
    for line in credit_span.lines {
    let annotation_range = line_annotation::range(env, open_file, line)?;
    let line_annotation_text = line_annotation::render(
    &localization_context,
    &open_repository.repository,
    open_file,
    &credit_span.value,
    )?;
    let hover_message = hover::render(
    env,
    &localization_context,
    &open_repository.repository,
    &credit_span.value,
    )?;
    let after = vscode_sys::ThemableDecorationAttachmentRenderOptions::new(env)?
    .content_text(&line_annotation_text)?;
    let render_options =
    vscode_sys::DecorationInstanceRenderOptions::new(env)?.after(after)?;
    let decoration_options =
    vscode_sys::DecorationOptions::new(env, &annotation_range)?
    .hover_message(&hover_message)?
    .render_options(render_options)?;
    decoration_options_list.push(decoration_options);
    }
    }
    }
    let decoration_type = program_state.decoration_type.get_inner(env)?;
    editor.set_decorations(decoration_type, decoration_options_list)?;
    Ok(())
  • file move: inline_credit.rs (----------)line_annotation.rs (----------)
    [2.122472]
    [2.123336]
  • edit in extensions/vscode/src/inline_credit/line_annotation.rs at line 1
    [2.123336][2.123337:123379]()
    // TODO: better, localized hover messages
  • edit in extensions/vscode/src/inline_credit/line_annotation.rs at line 2
    [2.123432][2.123432:123463]()
    use std::ops::RangeInclusive;
  • edit in extensions/vscode/src/inline_credit/line_annotation.rs at line 3
    [2.123464][2.123464:123513]()
    use camino::Utf8PathBuf;
    use icu_locale::locale;
  • edit in extensions/vscode/src/inline_credit/line_annotation.rs at line 6
    [2.123593][2.123593:123635]()
    use napi::bindgen_prelude::JsObjectValue;
  • edit in extensions/vscode/src/inline_credit/line_annotation.rs at line 8
    [2.123735][2.123735:123784]()
    use pijul_extension::file_system::changes::Span;
  • edit in extensions/vscode/src/inline_credit/line_annotation.rs at line 10
    [2.123840][2.123840:123867]()
    use crate::ExtensionState;
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 12
    [2.123891][2.123891:123932]()
    #[localize("l10n/**/inline_credit.ftl")]
    [2.123891]
    [2.123932]
    #[localize("l10n/**/inline_credit/line_annotation.ftl")]
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 23
    [2.124111][2.124111:124198]()
    #[localize("l10n/**/inline_credit.ftl")]
    enum InlineCreditAnnotation<'change_header> {
    [2.124111]
    [2.124198]
    #[localize("l10n/**/inline_credit/line_annotation.ftl")]
    enum LineAnnotation<'change_header> {
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 35
    [2.124415][2.124415:124611]()
    fn get_lines_selected(
    editor_selections: Vec<vscode_sys::Selection>,
    ) -> Result<Vec<RangeInclusive<usize>>, napi::Error> {
    let mut credits = Vec::with_capacity(editor_selections.len());
    [2.124415]
    [2.124611]
    pub fn range<'env>(
    env: &'env napi::Env,
    open_file: &OpenFile,
    line: usize,
    ) -> Result<vscode_sys::Range<'env>, napi::Error> {
    let current_line_contents = open_file
    .contents
    .text
    .get_line(line, ropey::LineType::LF_CR)
    .ok_or_else(|| napi::Error::from_reason(format!("no contents for line {line}")))?;
    let final_character_offset = current_line_contents.len() as u32;
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 47
    [2.124612][2.124612:124872]()
    for editor_selection in &editor_selections {
    let start_line = editor_selection.get_start()?.get_line()?;
    let end_line: u32 = editor_selection.get_end()?.get_line()?;
    credits.push((start_line as usize)..=(end_line as usize));
    }
    [2.124612]
    [2.124872]
    let start = vscode_sys::Position::new(env, line as u32, final_character_offset)?;
    let end = vscode_sys::Position::new(env, line as u32, final_character_offset)?;
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 50
    [2.124873][2.124873:124889]()
    Ok(credits)
    [2.124873]
    [2.124889]
    vscode_sys::Range::new(env, &start, &end)
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 53
    [2.124892][2.124892:124942]()
    fn decoration_options<'env>(
    env: &napi::Env,
    [2.124892]
    [2.124942]
    pub fn render(
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 57
    [2.125055][2.125055:126443]()
    credits: impl Iterator<Item = Span<CreditSource>>,
    ) -> Result<Vec<vscode_sys::DecorationOptions<'env>>, napi::Error> {
    let mut decoration_options_list = Vec::new();
    for credit in credits {
    tracing::debug!(?credit);
    let annotation = match credit.value {
    CreditSource::Tracked(change_id) => {
    let change_header = repository.get_change_header(&change_id).ok_or_else(|| {
    napi::Error::from_reason(format!("unable to get change {change_id:#?}"))
    })?;
    let authors = repository
    .authors_for_change(change_header)
    .into_iter()
    .map(|author_source| match author_source {
    pijul_extension::author::AuthorSource::Local(_identity) => {
    AuthorKind::Local
    }
    pijul_extension::author::AuthorSource::Remote(identity) => {
    AuthorKind::Remote {
    username: &identity.config.author.username,
    }
    }
    pijul_extension::author::AuthorSource::Unknown(public_key_signature) => {
    AuthorKind::Unknown {
    public_key_signature,
    }
    [2.125055]
    [2.126443]
    credit_source: &CreditSource,
    ) -> Result<String, napi::Error> {
    let annotation = match credit_source {
    CreditSource::Tracked(change_id) => {
    let change_header = repository.get_change_header(change_id).ok_or_else(|| {
    napi::Error::from_reason(format!("unable to get change {change_id:#?}"))
    })?;
    let authors = repository
    .authors_for_change(change_header)
    .into_iter()
    .map(|author_source| match author_source {
    pijul_extension::author::AuthorSource::Local(_identity) => AuthorKind::Local,
    pijul_extension::author::AuthorSource::Remote(identity) => AuthorKind::Remote {
    username: &identity.config.author.username,
    },
    pijul_extension::author::AuthorSource::Unknown(public_key_signature) => {
    AuthorKind::Unknown {
    public_key_signature,
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 76
    [2.126469][2.126469:126524]()
    })
    .collect();
    [2.126469]
    [2.126524]
    }
    })
    .collect();
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 80
    [2.126525][2.126525:126772]()
    InlineCreditAnnotation::Tracked {
    authors: l10n_embed::list::AndList::new(authors),
    timestamp: change_header.timestamp,
    message: &change_header.message,
    }
    [2.126525]
    [2.126772]
    LineAnnotation::Tracked {
    authors: l10n_embed::list::AndList::new(authors),
    timestamp: change_header.timestamp,
    message: &change_header.message,
  • edit in extensions/vscode/src/inline_credit/line_annotation.rs at line 85
    [2.126786][2.126786:129438]()
    CreditSource::Untracked => InlineCreditAnnotation::Untracked {
    timestamp: Timestamp::try_from(open_file.contents.modified_time).map_err(
    |error| {
    napi::Error::from_reason(format!(
    "Failed to parse timestamp {:#?}: {error}",
    open_file.contents.modified_time
    ))
    },
    )?,
    },
    };
    let mut localized_annotation = String::new();
    annotation.localize(localization_context, &mut localized_annotation);
    let hover_message_text = match credit.value {
    CreditSource::Tracked(change_id) => {
    let change_header = repository.get_change_header(&change_id).ok_or_else(|| {
    napi::Error::from_reason(format!("unable to get change {change_id:#?}"))
    })?;
    match &change_header.description {
    Some(description) => {
    format!("<h2>{}</h2><p>{}</p>", change_header.message, description)
    }
    None => change_header.message.clone(),
    }
    }
    CreditSource::Untracked => String::new(),
    };
    for line in credit.lines {
    let current_line_contents = open_file
    .contents
    .text
    .get_line(line, ropey::LineType::LF_CR)
    .ok_or_else(|| napi::Error::from_reason(format!("no contents for line {line}")))?;
    let final_character_offset = current_line_contents.len() as u32;
    let start = vscode_sys::Position::new(env, line as u32, final_character_offset)?;
    let end = vscode_sys::Position::new(env, line as u32, final_character_offset)?;
    let range = vscode_sys::Range::new(env, &start, &end)?;
    let mut hover_message =
    vscode_sys::MarkdownString::new(env, &hover_message_text, false)?;
    hover_message
    .inner
    .set_named_property("supportHtml", true)?;
    let after = vscode_sys::ThemableDecorationAttachmentRenderOptions::new(env)?
    .content_text(&localized_annotation)?;
    let render_options =
    vscode_sys::DecorationInstanceRenderOptions::new(env)?.after(after)?;
    let decoration_options = vscode_sys::DecorationOptions::new(env, &range)?
    .hover_message(&hover_message)?
    .render_options(render_options)?;
    decoration_options_list.push(decoration_options);
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 86
    [2.129448][2.129448:130273]()
    }
    Ok(decoration_options_list)
    }
    // TODO: different rendering modes? e.g. render only at boundaries between lines, render only on cursors, etc
    pub fn render(
    env: &napi::Env,
    program_state: &ExtensionState,
    editor: &vscode_sys::TextEditor,
    selections: Vec<vscode_sys::Selection>,
    ) -> Result<(), napi::Error> {
    let editor_document = editor.get_document()?;
    let document_uri = editor_document.get_uri()?;
    let Some((repository_path, open_repository)) = program_state
    .repositories
    .get_open_repository(env, &document_uri)?
    else {
    return Ok(());
    };
    let absolute_file_path = Utf8PathBuf::from(document_uri.get_fs_path()?);
    let relative_file_path =
    absolute_file_path
    .strip_prefix(&repository_path)
    .map_err(|error| {
    [2.129448]
    [2.130273]
    CreditSource::Untracked => LineAnnotation::Untracked {
    // TODO: return the current time if `TextDocument::get_is_dirty()`
    timestamp: Timestamp::try_from(open_file.contents.modified_time).map_err(|error| {
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 90
    [2.130323][2.130323:130421]()
    "Failed to strip prefix {repository_path} from {absolute_file_path}: {error}"
    [2.130323]
    [2.130421]
    "Failed to parse timestamp {:#?}: {error}",
    open_file.contents.modified_time
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 93
    [2.130440][2.130440:131126]()
    })?;
    let localization_context = l10n_embed::Context::new(locale!("en-US"), false);
    let lines_selected = get_lines_selected(selections)?;
    let open_file = open_repository
    .repository
    .get_open_file(relative_file_path)
    .ok_or_else(|| {
    napi::Error::from_reason(format!("unable to get open file for {relative_file_path}"))
    })?;
    let credits = lines_selected
    .into_iter()
    .flat_map(|line_range| open_file.credit(line_range));
    let decoration_options = decoration_options(
    env,
    &localization_context,
    &open_repository.repository,
    open_file,
    credits,
    )?;
    [2.130440]
    [2.131126]
    })?,
    },
    };
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 97
    [2.131127][2.131127:131266]()
    let decoration_type = program_state.decoration_type.get_inner(env)?;
    editor.set_decorations(decoration_type, decoration_options)?;
    [2.131127]
    [2.131266]
    let mut localized_annotation = String::new();
    annotation.localize(localization_context, &mut localized_annotation);
  • replacement in extensions/vscode/src/inline_credit/line_annotation.rs at line 100
    [2.131267][2.131267:131278]()
    Ok(())
    [2.131267]
    [2.131278]
    Ok(localized_annotation)
  • file addition: hover.rs (----------)
    [2.122472]
    use std::borrow::Cow;
    use askama::Template;
    use icu_datetime::{DateTimeFormatter, DateTimeFormatterPreferences};
    use jiff::tz::TimeZone;
    use jiff_icu::ConvertFrom;
    use l10n_embed::Localize;
    use l10n_embed_derive::localize;
    use libpijul::Base32;
    use pijul_extension::FileSystemRepository;
    use pijul_extension::author::AuthorSource;
    use pijul_extension::file_system::changes::CreditSource;
    use crate::vscode_sys;
    #[localize("l10n/**/inline_credit/hover.ftl")]
    enum HoverHeading {
    AbsoluteTimestamp,
    ChangeId,
    }
    #[derive(askama::Template)]
    #[template(path = "hover/tracked.html")]
    struct TrackedHoverTemplate<'change_header> {
    title: &'change_header str,
    authors: String,
    relative_timestamp: String,
    absolute_timestamp_header: String,
    absolute_timestamp: String,
    change_id_header: String,
    // TODO: color/emphasize unique portion of ID (e.g. *ABC*DEFGHIJKL)
    change_id: String,
    description: Option<&'change_header str>,
    }
    #[derive(askama::Template)]
    #[template(path = "hover/untracked.html")]
    struct UntrackedHoverTemplate;
    pub fn render<'env>(
    env: &'env napi::Env,
    localization_context: &l10n_embed::Context,
    repository: &FileSystemRepository,
    credit_source: &CreditSource,
    ) -> Result<vscode_sys::MarkdownString<'env>, napi::Error> {
    let rendered_html_result = match credit_source {
    CreditSource::Tracked(change_id) => {
    let change_header = repository.get_change_header(change_id).ok_or_else(|| {
    napi::Error::from_reason(format!("unable to get change {change_id:#?}"))
    })?;
    let mut authors = String::new();
    let authors_list = l10n_embed::list::AndList::new(
    repository
    .authors_for_change(change_header)
    .into_iter()
    .map(|author_source| match author_source {
    AuthorSource::Local(identity) | AuthorSource::Remote(identity) => {
    Cow::from(format!(
    "{} ({})",
    identity.config.author.display_name,
    identity.config.author.username
    ))
    }
    AuthorSource::Unknown(public_key_hash) => Cow::from(public_key_hash),
    })
    .collect(),
    );
    authors_list.localize(localization_context, &mut authors);
    let mut relative_timestamp = String::new();
    change_header
    .timestamp
    .localize(localization_context, &mut relative_timestamp);
    let mut absolute_timestamp_header = String::new();
    let mut change_id_header = String::new();
    HoverHeading::AbsoluteTimestamp
    .localize(localization_context, &mut absolute_timestamp_header);
    HoverHeading::ChangeId.localize(localization_context, &mut change_id_header);
    // TODO: properly localize using l10n_embed
    let zoned_timestamp = change_header.timestamp.to_zoned(TimeZone::system());
    let icu_timestamp = icu_time::ZonedDateTime::<
    icu_calendar::Iso,
    icu_time::TimeZoneInfo<icu_time::zone::models::Full>,
    >::convert_from(&zoned_timestamp);
    let absolute_timestamp_formatter = DateTimeFormatter::try_new(
    DateTimeFormatterPreferences::from(&localization_context.locale),
    icu_datetime::fieldsets::YMDT::medium()
    .with_zone(icu_datetime::fieldsets::zone::SpecificShort),
    )
    .map_err(|error| {
    napi::Error::from_reason(format!("Failed to create datetime formatter: {error}"))
    })?;
    let absolute_timestamp = absolute_timestamp_formatter
    .format(&icu_timestamp)
    .to_string();
    let hover_template = TrackedHoverTemplate {
    title: &change_header.message,
    authors,
    relative_timestamp,
    absolute_timestamp_header,
    absolute_timestamp,
    change_id_header,
    change_id: change_id.to_base32(),
    description: change_header.description.as_deref(),
    };
    hover_template.render()
    }
    CreditSource::Untracked => {
    let hover_template = UntrackedHoverTemplate;
    hover_template.render()
    }
    };
    let rendered_html = rendered_html_result.map_err(|error| {
    napi::Error::from_reason(format!("Failed to render hover message: {error}"))
    })?;
    let mut hover_message = vscode_sys::MarkdownString::new(env, &rendered_html, false)?;
    hover_message.set_support_html(true)?;
    Ok(hover_message)
    }
  • file addition: inline_credit (d--r------)
    [2.175094]
  • file move: inline_credit.ftl (----------)line_annotation.ftl (----------)
    [0.11982]
    [2.175138]
  • file addition: hover.ftl (----------)
    [0.11982]
    absolute-timestamp = Timestamp
    change-id = Change ID
  • edit in extensions/vscode/Cargo.toml at line 20
    [2.175821]
    [2.175821]
    askama.workspace = true
  • edit in extensions/vscode/Cargo.toml at line 22
    [2.175845]
    [2.175845]
    icu_calendar.workspace = true
    icu_datetime.workspace = true
  • edit in extensions/vscode/Cargo.toml at line 25
    [2.175873]
    [2.175873]
    icu_time.workspace = true
  • replacement in extensions/vscode/Cargo.toml at line 27
    [2.175895][2.175895:175923]()
    l10n_embed.workspace = true
    [2.175895]
    [2.175923]
    jiff-icu.workspace = true
  • replacement in extensions/vscode/Cargo.toml at line 29
    [2.175958][2.175958:175980]()
    napi.workspace = true
    [2.175958]
    [2.175980]
    l10n_embed.workspace = true
    libpijul.workspace = true
  • edit in extensions/vscode/Cargo.toml at line 33
    [2.176035]
    [2.176035]
    napi.workspace = true
  • edit in extensions/vscode/Cargo.toml at line 35
    [2.176058]
    [2.176058]
    tracing-subscriber.workspace = true
  • edit in extensions/vscode/Cargo.toml at line 37
    [2.176083][2.176083:176119]()
    tracing-subscriber.workspace = true
  • edit in Cargo.toml at line 24
    [2.176747]
    [2.176747]
    askama = "0.14"
  • edit in Cargo.toml at line 29
    [2.176859]
    [2.176859]
    icu_calendar = "2.0"
    icu_datetime = "2.0"
  • edit in Cargo.toml at line 32
    [2.176878]
    [2.176878]
    icu_time = "2.0"
  • edit in Cargo.toml at line 34
    [2.176891]
    [2.176891]
    jiff-icu = "0.2"
  • edit in Cargo.lock at line 124
    [2.180601]
    [2.180601]
    [[package]]
    name = "askama"
    version = "0.14.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4"
    dependencies = [
    "askama_derive",
    "itoa",
    "percent-encoding",
    "serde",
    "serde_json",
    ]
    [[package]]
    name = "askama_derive"
    version = "0.14.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f"
    dependencies = [
    "askama_parser",
    "basic-toml",
    "memchr",
    "proc-macro2",
    "quote",
    "rustc-hash",
    "serde",
    "serde_derive",
    "syn",
    ]
  • edit in Cargo.lock at line 156
    [2.180614]
    [2.180614]
    name = "askama_parser"
    version = "0.14.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358"
    dependencies = [
    "memchr",
    "serde",
    "serde_derive",
    "winnow",
    ]
    [[package]]
  • edit in Cargo.lock at line 217
    [2.181937]
    [2.181937]
    [[package]]
    name = "basic-toml"
    version = "0.1.10"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a"
    dependencies = [
    "serde",
    ]
  • edit in Cargo.lock at line 366
    [2.185651]
    [2.185651]
    name = "calendrical_calculations"
    version = "0.2.3"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "3a0b39595c6ee54a8d0900204ba4c401d0ab4eb45adaf07178e8d017541529e7"
    dependencies = [
    "core_maths",
    "displaydoc",
    ]
    [[package]]
  • edit in Cargo.lock at line 590
    [2.191117]
    [2.191117]
    [[package]]
    name = "core_maths"
    version = "0.1.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30"
    dependencies = [
    "libm",
    ]
  • edit in Cargo.lock at line 1302
    [2.208902]
    [2.208902]
    name = "icu_calendar"
    version = "2.0.6"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "362941891d17750e05cd8fdfca4a89a86552825d625a937020ee1a65580da1f9"
    dependencies = [
    "calendrical_calculations",
    "displaydoc",
    "icu_calendar_data",
    "icu_locale",
    "icu_locale_core",
    "icu_provider",
    "ixdtf",
    "tinystr",
    "writeable",
    "zerovec",
    ]
    [[package]]
    name = "icu_calendar_data"
    version = "2.0.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "7219c8639ab936713a87b571eed2bc2615aa9137e8af6eb221446ee5644acc18"
    [[package]]
  • edit in Cargo.lock at line 1359
    [2.209740]
    [2.209740]
    "zerovec",
    ]
    [[package]]
    name = "icu_datetime"
    version = "2.0.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "eea7ff7a9d7ce8f419930ec75b9821807cdbde7ec5f0157c322773a6ede6125f"
    dependencies = [
    "displaydoc",
    "either",
    "fixed_decimal",
    "icu_calendar",
    "icu_datetime_data",
    "icu_decimal",
    "icu_locale",
    "icu_locale_core",
    "icu_pattern",
    "icu_plurals",
    "icu_provider",
    "icu_time",
    "potential_utf",
    "smallvec",
    "tinystr",
    "writeable",
  • edit in Cargo.lock at line 1386
    [2.209754]
    [2.209754]
    [[package]]
    name = "icu_datetime_data"
    version = "2.0.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "83791ac10bb7b774f130bb81fa89c4059de710dcef53caa0b86e645212d6d54c"
  • edit in Cargo.lock at line 1609
    [2.214769]
    [2.214769]
    name = "icu_time"
    version = "2.0.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "b49a81ac920c1a93e3165a5f16d16f5c15d9f19fc5dc1223c00af35f7a7c2bb6"
    dependencies = [
    "calendrical_calculations",
    "displaydoc",
    "icu_calendar",
    "icu_locale_core",
    "icu_provider",
    "icu_time_data",
    "ixdtf",
    "serde",
    "tinystr",
    "writeable",
    "zerotrie",
    "zerovec",
    ]
    [[package]]
    name = "icu_time_data"
    version = "2.0.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "8472be4410d26a03d7208cae3a76c798dd6766e8226ab977cd8b2d349a6dbf08"
    [[package]]
  • edit in Cargo.lock at line 1769
    [2.218131]
    [2.218131]
    name = "ixdtf"
    version = "0.5.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "8289f7f711a1a51f80e2e368355d023042ca55d8d554fd5e953f01464c15842d"
    dependencies = [
    "displaydoc",
    ]
    [[package]]
  • edit in Cargo.lock at line 1793
    [2.218464]
    [2.218464]
    name = "jiff-icu"
    version = "0.2.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "0e67c2beaae8b10a82d849b9aabb698a43a682f32b17bcdc035d5ecadb44d646"
    dependencies = [
    "icu_calendar",
    "icu_time",
    "jiff",
    ]
    [[package]]
  • edit in Cargo.lock at line 1924
    [2.221351]
    [2.221351]
    [[package]]
    name = "libm"
    version = "0.2.15"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
  • edit in Cargo.lock at line 2558
    [2.235734]
    [2.235734]
    "askama",
  • edit in Cargo.lock at line 2560
    [2.235745]
    [2.235745]
    "icu_calendar",
    "icu_datetime",
  • edit in Cargo.lock at line 2563
    [2.235760]
    [2.235760]
    "icu_time",
  • edit in Cargo.lock at line 2565
    [2.235769]
    [2.235769]
    "jiff-icu",
  • edit in Cargo.lock at line 2568
    [2.235806]
    [2.235806]
    "libpijul",