diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 666f7a88..eeb35eb1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,7 +78,7 @@ jobs: - { rust: stable, vendor: Toshiba, options: all } - { rust: stable, vendor: Toshiba, options: "" } # Test MSRV - - { rust: 1.64.0, vendor: Nordic, options: "" } + - { rust: 1.65.0, vendor: Nordic, options: "" } # Use nightly for architectures which don't support stable - { rust: nightly, vendor: MSP430, options: "--atomics" } - { rust: nightly, vendor: MSP430, options: "" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 437a04d2..bcc8faad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ## [Unreleased] -- Bump MSRV to 1.64 +- Bump MSRV to 1.65 - Fix dangling implicit derives +- Fix escaping <> and & characters in doc attributes ## [v0.28.0] - 2022-12-25 diff --git a/Cargo.toml b/Cargo.toml index 9c90a853..c8755bfd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,7 @@ serde = { version = "1.0", optional = true } serde_json = { version = "1.0.85", optional = true } serde_yaml = { version = "0.9.11", optional = true } regex = "1.7.0" +html-escape = "0.2" [dependencies.svd-parser] features = ["expand"] diff --git a/README.md b/README.md index e83bcf63..2022b4a8 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ This project is developed and maintained by the [Tools team][team]. ## Minimum Supported Rust Version (MSRV) -The **generated code** is guaranteed to compile on stable Rust 1.64.0 and up. +The **generated code** is guaranteed to compile on stable Rust 1.65.0 and up. -If you encounter compilation errors on any stable version newer than 1.64.0, please open an issue. +If you encounter compilation errors on any stable version newer than 1.65.0, please open an issue. # Testing Locally diff --git a/src/generate/interrupt.rs b/src/generate/interrupt.rs index 499cbe09..0f826f6a 100644 --- a/src/generate/interrupt.rs +++ b/src/generate/interrupt.rs @@ -63,7 +63,7 @@ pub fn render( .as_ref() .map(|s| util::respace(s)) .as_ref() - .map(|s| util::escape_brackets(s)) + .map(|s| util::escape_special_chars(s)) .unwrap_or_else(|| interrupt.0.name.clone()) ); diff --git a/src/generate/peripheral.rs b/src/generate/peripheral.rs index 0486c1cd..90cdfece 100644 --- a/src/generate/peripheral.rs +++ b/src/generate/peripheral.rs @@ -184,7 +184,7 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result } } - let description = util::escape_brackets( + let description = util::escape_special_chars( util::respace(p.description.as_ref().unwrap_or(&name.as_ref().to_owned())).as_ref(), ); @@ -516,7 +516,7 @@ impl FieldRegions { } fn make_comment(size: u32, offset: u32, description: &str) -> String { - let desc = util::escape_brackets(&util::respace(description)); + let desc = util::escape_special_chars(&util::respace(description)); if size > 32 { let end = offset + size / 8; format!("0x{offset:02x}..0x{end:02x} - {desc}") @@ -1306,7 +1306,7 @@ fn cluster_block( config: &Config, ) -> Result { let description = - util::escape_brackets(&util::respace(c.description.as_ref().unwrap_or(&c.name))); + util::escape_special_chars(&util::respace(c.description.as_ref().unwrap_or(&c.name))); let mod_name = util::replace_suffix(&c.name, ""); // name_snake_case needs to take into account array type. diff --git a/src/generate/register.rs b/src/generate/register.rs index 0aa8291d..801b24e0 100644 --- a/src/generate/register.rs +++ b/src/generate/register.rs @@ -39,7 +39,7 @@ pub fn render( let span = Span::call_site(); let name_constant_case = name.to_constant_case_ident(span); let name_snake_case = name.to_snake_case_ident(span); - let description = util::escape_brackets( + let description = util::escape_special_chars( util::respace(®ister.description.clone().unwrap_or_else(|| { warn!("Missing description for register {}", register.name); Default::default() @@ -129,7 +129,7 @@ pub fn render_register_mod( rsize.next_power_of_two() }; let rty = rsize.to_ty()?; - let description = util::escape_brackets( + let description = util::escape_special_chars( util::respace(®ister.description.clone().unwrap_or_else(|| { warn!("Missing description for register {}", register.name); Default::default() @@ -436,7 +436,7 @@ pub fn fields( let name_snake_case = name.to_snake_case_ident(span); let name_constant_case = name.to_sanitized_constant_case(); let description_raw = f.description.as_deref().unwrap_or(""); // raw description, if absent using empty string - let description = util::respace(&util::escape_brackets(description_raw)); + let description = util::respace(&util::escape_special_chars(description_raw)); let can_read = can_read && (f.access != Some(Access::WriteOnly)) @@ -833,7 +833,7 @@ pub fn fields( for v in &variants { let pc = &v.pc; let sc = &v.sc; - let doc = util::escape_brackets(&util::respace(&v.doc)); + let doc = util::escape_special_chars(&util::respace(&v.doc)); proxy_items.extend(quote! { #[doc = #doc] #inline @@ -1105,7 +1105,7 @@ fn add_from_variants( let mut vars = TokenStream::new(); for v in variants.iter().map(|v| { - let desc = util::escape_brackets(&util::respace(&format!("{}: {}", v.value, v.doc))); + let desc = util::escape_special_chars(&util::respace(&format!("{}: {}", v.value, v.doc))); let pcv = &v.pc; let pcval = &util::unsuffixed(v.value); quote! { @@ -1178,7 +1178,7 @@ fn description_with_bits(description: &str, offset: u64, width: u32) -> String { }; if !description.is_empty() { res.push_str(" - "); - res.push_str(&util::respace(&util::escape_brackets(description))); + res.push_str(&util::respace(&util::escape_special_chars(description))); } res } diff --git a/src/util.rs b/src/util.rs index 6f96d64c..3dca4470 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use crate::svd::{Access, Device, DimElement, Field, RegisterInfo, RegisterProperties}; +use html_escape::encode_text_minimal; use inflections::Inflect; use proc_macro2::{Ident, Span, TokenStream}; use quote::quote; @@ -287,6 +288,12 @@ pub fn escape_brackets(s: &str) -> String { }) } +/// Escape basic html tags and brackets +pub fn escape_special_chars(s: &str) -> String { + let html_escaped = encode_text_minimal(s); + escape_brackets(&html_escaped) +} + pub fn name_of(maybe_array: &MaybeArray, ignore_group: bool) -> Cow { match maybe_array { MaybeArray::Single(info) => info.fullname(ignore_group),