Skip to content

Commit

Permalink
release: 0.5.8
Browse files Browse the repository at this point in the history
  • Loading branch information
joshstoik1 committed Nov 29, 2024
2 parents 4a44ea5 + 7045f77 commit 95a6345
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 80 deletions.
39 changes: 25 additions & 14 deletions CREDITS.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
# Project Dependencies
Package: yesvgmap
Version: 0.5.7
Generated: 2024-10-18 03:14:56 UTC
Version: 0.5.8
Target: x86_64-unknown-linux-gnu
Generated: 2024-11-29 05:26:31 UTC

| Package | Version | Author(s) | License |
| ---- | ---- | ---- | ---- |
| [ahash](https://github.com/tkaitchuck/ahash) | 0.8.11 | [Tom Kaitchuck](mailto:[email protected]) | Apache-2.0 or MIT |
| [argyle](https://github.com/Blobfolio/argyle) | 0.10.0 | [Blobfolio, LLC.](mailto:[email protected]) | WTFPL |
| [cfg-if](https://github.com/alexcrichton/cfg-if) | 1.0.0 | [Alex Crichton](mailto:[email protected]) | Apache-2.0 or MIT |
| [dactyl](https://github.com/Blobfolio/dactyl) | 0.7.4 | [Blobfolio, LLC.](mailto:[email protected]) | WTFPL |
| [dowser](https://github.com/Blobfolio/dowser) | 0.9.3 | [Blobfolio, LLC.](mailto:[email protected]) | WTFPL |
| [fastrand](https://github.com/smol-rs/fastrand) | 2.1.1 | [Stjepan Glavina](mailto:[email protected]) | Apache-2.0 or MIT |
| [fyi_msg](https://github.com/Blobfolio/fyi) | 1.1.1 | [Blobfolio, LLC.](mailto:[email protected]) | WTFPL |
| [once_cell](https://github.com/matklad/once_cell) | 1.20.2 | [Aleksey Kladov](mailto:[email protected]) | Apache-2.0 or MIT |
| [svg](https://github.com/bodoni/svg) | 0.18.0 | [Adam Bryant](mailto:[email protected]), [Felix Schütt](mailto:[email protected]), [Felix Zwettler](mailto:[email protected]), [GeoffreyY](mailto:[email protected]), [Gijs Burghoorn](mailto:[email protected]), [Ivan Ukhov](mailto:[email protected]), [Jack Greenbaum](mailto:[email protected]), [Joshua Klein](mailto:[email protected]), [Mike Wilkerson](mailto:[email protected]), [Nathan Hüsken](mailto:[email protected]), [Nathaniel Cook](mailto:[email protected]), [Nick Angelou](mailto:[email protected]), [Nicolas Silva](mailto:[email protected]), [Nor Khasyatillah](mailto:[email protected]), [OCTronics](mailto:[email protected]), [Patrick Chieppe](mailto:[email protected]), [Will Nelson](mailto:[email protected]), [Xander Rudelis](mailto:[email protected]), [e-matteson](mailto:[email protected]), and [kmkzt](mailto:[email protected]) | Apache-2.0 or MIT |
| [tempfile](https://github.com/Stebalien/tempfile) | 3.13.0 | [Steven Allen](mailto:[email protected]), The Rust Project Developers, [Ashley Mannix](mailto:[email protected]), and [Jason White](mailto:[email protected]) | Apache-2.0 or MIT |
| [write_atomic](https://github.com/Blobfolio/write_atomic) | 0.5.1 | [Blobfolio, LLC.](mailto:[email protected]) | WTFPL |
| [zerocopy](https://github.com/google/zerocopy) | 0.7.35 | [Joshua Liebow-Feeser](mailto:[email protected]) | Apache-2.0, BSD-2-Clause, or MIT |
| [ahash](https://github.com/tkaitchuck/ahash) | 0.8.11 | [Tom Kaitchuck](mailto:[email protected]) | MIT OR Apache-2.0 |
| [**argyle**](https://github.com/Blobfolio/argyle) | 0.10.1 | [Josh Stoik](mailto:[email protected]) | WTFPL |
| [bitflags](https://github.com/bitflags/bitflags) | 2.6.0 | The Rust Project Developers | MIT OR Apache-2.0 |
| [cfg-if](https://github.com/alexcrichton/cfg-if) | 1.0.0 | [Alex Crichton](mailto:[email protected]) | MIT OR Apache-2.0 |
| [**dactyl**](https://github.com/Blobfolio/dactyl) | 0.8.0 | [Josh Stoik](mailto:[email protected]) | WTFPL |
| [**dowser**](https://github.com/Blobfolio/dowser) | 0.10.1 | [Josh Stoik](mailto:[email protected]) | WTFPL |
| [fastrand](https://github.com/smol-rs/fastrand) | 2.2.0 | [Stjepan Glavina](mailto:[email protected]) | Apache-2.0 OR MIT |
| [**fyi_msg**](https://github.com/Blobfolio/fyi) | 1.3.0 | [Josh Stoik](mailto:[email protected]) | WTFPL |
| [linux-raw-sys](https://github.com/sunfishcode/linux-raw-sys) | 0.4.14 | [Dan Gohman](mailto:[email protected]) | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT |
| [once_cell](https://github.com/matklad/once_cell) | 1.20.2 | [Aleksey Kladov](mailto:[email protected]) | MIT OR Apache-2.0 |
| [rustix](https://github.com/bytecodealliance/rustix) | 0.38.41 | [Dan Gohman](mailto:[email protected]) and [Jakub Konka](mailto:[email protected]) | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT |
| [**svg**](https://github.com/bodoni/svg) | 0.18.0 | [Adam Bryant](mailto:[email protected]), [Felix Schütt](mailto:[email protected]), [Felix Zwettler](mailto:[email protected]), [GeoffreyY](mailto:[email protected]), [Gijs Burghoorn](mailto:[email protected]), [Ivan Ukhov](mailto:[email protected]), [Jack Greenbaum](mailto:[email protected]), [Joshua Klein](mailto:[email protected]), [Mike Wilkerson](mailto:[email protected]), [Nathan Hüsken](mailto:[email protected]), [Nathaniel Cook](mailto:[email protected]), [Nick Angelou](mailto:[email protected]), [Nicolas Silva](mailto:[email protected]), [Nor Khasyatillah](mailto:[email protected]), [OCTronics](mailto:[email protected]), [Patrick Chieppe](mailto:[email protected]), [Will Nelson](mailto:[email protected]), [Xander Rudelis](mailto:[email protected]), [e-matteson](mailto:[email protected]), and [kmkzt](mailto:[email protected]) | Apache-2.0 OR MIT |
| [tempfile](https://github.com/Stebalien/tempfile) | 3.14.0 | [Steven Allen](mailto:[email protected]), The Rust Project Developers, [Ashley Mannix](mailto:[email protected]), and [Jason White](mailto:[email protected]) | MIT OR Apache-2.0 |
| [version_check](https://github.com/SergioBenitez/version_check) ⚒️ | 0.9.5 | [Sergio Benitez](mailto:[email protected]) | MIT OR Apache-2.0 |
| [**write_atomic**](https://github.com/Blobfolio/write_atomic) | 0.5.2 | [Josh Stoik](mailto:[email protected]) | WTFPL |
| [zerocopy](https://github.com/google/zerocopy) | 0.7.35 | [Joshua Liebow-Feeser](mailto:[email protected]) | BSD-2-Clause OR Apache-2.0 OR MIT |

### Legend

* **Direct Dependency**
* Child Dependency
* ⚒️ Build-Only
13 changes: 6 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "yesvgmap"
version = "0.5.7"
version = "0.5.8"
license = "WTFPL"
authors = ["Josh Stoik <[email protected]>"]
edition = "2021"
Expand All @@ -10,7 +10,7 @@ readme = "README.md"
publish = false

[package.metadata.deb]
maintainer = "Josh Stoik <hello@blobfolio.com>"
maintainer = "Josh Stoik <josh@blobfolio.com>"
copyright = "2024, Blobfolio, LLC <[email protected]>"
license-file = ["./LICENSE", "0"]
revision = "1"
Expand All @@ -27,7 +27,6 @@ assets = [
name = "Yesvgmap"
bash-dir = "./release/completions"
man-dir = "./release/man"
credits-dir = "./"

[[package.metadata.bashman.switches]]
short = "-h"
Expand Down Expand Up @@ -83,13 +82,13 @@ description = "One or more file and/or directory paths to crunch and/or (recursi

[build-dependencies]
argyle = "0.10.*"
dowser = "0.9.*"
dowser = "0.10.*"

[dependencies]
argyle = "0.10.*"
dactyl = "0.7.*"
dowser = "0.9.*"
fyi_msg = "1.1.*"
dactyl = "0.8.*"
dowser = "0.10.*"
fyi_msg = "1.3.*"
svg = "=0.18.0"
write_atomic = "0.5.*"

Expand Down
24 changes: 0 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,27 +107,3 @@ Generally speaking, directly inlining an SVG makes more sense than using a sprit
* The image only appears once;
* You need to be able to manipulate its `<path>`s at runtime for e.g. animation;
* It has no `viewBox` or requires canvas overflow for proper display;



## License

See also: [CREDITS.md](CREDITS.md)

Copyright © 2024 [Blobfolio, LLC](https://blobfolio.com) &lt;[email protected]&gt;

This work is free. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2.

DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004

Copyright (C) 2004 Sam Hocevar <[email protected]>

Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.

DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. You just DO WHAT THE FUCK YOU WANT TO.
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export RUSTFLAGS := "-C target-cpu=x86-64-v3"

# Generate CREDITS.
@credits:
cargo bashman -m "{{ pkg_dir1 }}/Cargo.toml"
cargo bashman -m "{{ pkg_dir1 }}/Cargo.toml" -t x86_64-unknown-linux-gnu
just _fix-chown "{{ justfile_directory() }}/CREDITS.md"


Expand Down
7 changes: 4 additions & 3 deletions release/man/yesvgmap.1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.TH "YESVGMAP" "1" "October 2024" "yesvgmap v0.5.7" "User Commands"
.TH "YESVGMAP" "1" "November 2024" "yesvgmap v0.5.8" "User Commands"
.SH NAME
YESVGMAP \- Manual page for yesvgmap v0.5.7.
YESVGMAP \- Manual page for yesvgmap v0.5.8.
.SH DESCRIPTION
Generate SVG sprite maps from individual SVG images.
.SS USAGE:
Expand Down Expand Up @@ -35,6 +35,7 @@ Save the generated map to this location. If omitted, the map will print to STDOU
.TP
\fB\-p\fR, \fB\-\-prefix\fR <PREFIX>
Set a custom prefix for the IDs of each entry in the map. (IDs look like PREFIX\-STEM, where STEM is the alphanumeric portion of the source file name, e.g. 'i\-close'.) [default: i]
.SS <PATH(S)…>:
.SS TRAILING:
.TP
\fB<PATH(s)…>\fR
One or more file and/or directory paths to crunch and/or (recursively) crawl. Only files with the extension .svg will ultimately be included.
4 changes: 4 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ pub(super) enum SvgError {
/// # Duplicate entry.
Duplicate(String),

/// # File Name (Stem).
FileName(PathBuf),

/// # No SVGs.
NoSvgs,

Expand Down Expand Up @@ -106,6 +109,7 @@ impl fmt::Display for SvgError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Duplicate(s) => write!(f, "Normalized name collision: {s}."),
Self::FileName(p) => write!(f, "File name has no ASCII alphanumeric or '-': {p:?}"),
Self::Parse(p) => write!(f, "Unable to parse: {p:?}."),
Self::Read(p) => write!(f, "Unreadable: {p:?}."),
Self::Viewbox(p) => write!(f, "Missing viewBox: {p:?}"),
Expand Down
98 changes: 76 additions & 22 deletions src/img.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use crate::SvgError;
use fyi_msg::Msg;
use std::{
borrow::Cow,
collections::BTreeMap,
fmt,
path::{
Expand Down Expand Up @@ -57,7 +58,7 @@ impl fmt::Display for Map {

// The hidden attribute shouldn't have a "true" attached to it.
if matches!(self.hide, HideType::Hidden) {
if let Some(pos) = raw.as_bytes().windows(14).position(|b| b == br#" hidden="true""#) {
if let Some(pos) = raw.find(r#" hidden="true""#) {
raw.replace_range(pos+7..pos+14, "");
}
}
Expand Down Expand Up @@ -87,7 +88,7 @@ impl Map {
class: Option<&str>,
hide: HideType,
prefix: &str,
paths: Vec<PathBuf>,
paths: &[PathBuf],
) -> Result<Self, SvgError> {
// There have to be paths.
if paths.is_empty() {
Expand Down Expand Up @@ -117,31 +118,28 @@ impl Map {
}

// Handle the paths!
let mut warned: Vec<String> = Vec::new();
let mut warned: Vec<Cow<str>> = Vec::new();
let len: usize = paths.len();
let mut nice_paths: BTreeMap<String, Symbol> = BTreeMap::default();
let mut nice_paths: BTreeMap<Cow<str>, Symbol> = BTreeMap::default();
for path in paths {
// The symbol ID is built from the alphanumeric (and dash)
// characters in the file name.
let stem: String = path.file_stem()
.ok_or_else(|| SvgError::Read(path.clone()))?
.to_string_lossy()
.chars()
.filter(|x| x.is_ascii_alphanumeric() || '-'.eq(x))
.collect();
let stem = parse_stem_id(path)
.ok_or_else(|| SvgError::FileName(path.clone()))?;

// Build up the symbol.
let (s, warn) = parse_as_symbol(&path, &stem, prefix)?;
let (s, warn) = parse_as_symbol(path, &stem, prefix)?;

// Push it to temporary storage.
if nice_paths.insert(stem.clone(), s).is_some() {
return Err(SvgError::Duplicate(stem));
return Err(SvgError::Duplicate(stem.into_owned()));
}

// Note if this has styles or other issues.
if warn {
if let Some(name) = path.file_name() {
warned.push(name.to_string_lossy().into_owned());
// TODO: keep name as-is; use .display for printing once stable.
warned.push(name.to_string_lossy());
}
}
}
Expand All @@ -155,7 +153,7 @@ contexts; the following image{} might need to be refactored:",
))
.eprint();

warned.sort();
warned.sort_unstable();
for w in warned {
eprintln!(" \x1b[1;93m•\x1b[0m {w}");
}
Expand Down Expand Up @@ -384,20 +382,39 @@ fn parse_main(event: Option<Event>, path: &Path) -> Result<Symbol, SvgError> {
Err(SvgError::Parse(path.to_path_buf()))
}

/// # Path Stem to ID.
///
/// Take the ASCII alphanumeric and `-` characters from the file stem and
/// return them for use as an ID suffix.
fn parse_stem_id(path: &Path) -> Option<Cow<'_, str>> {
let mut out = path.file_stem()?.to_string_lossy();

// Reduce to alphanumeric and -.
if out.chars().any(|c| c != '-' && ! c.is_ascii_alphanumeric()) {
out.to_mut().retain(|c: char| c == '-' || c.is_ascii_alphanumeric());
}

// Return it if we got it.
if out.is_empty() { None }
else { Some(out) }
}

/// # Parse Width/Height.
///
/// This attempts to build a `viewBox` value from a `width` and `height`,
/// returning `None` if either is missing or non-positive.
fn parse_wh(w1: Option<&Value>, h1: Option<&Value>) -> Option<String> {
let w1 = w1?.to_string();
let h1 = h1?.to_string();

let w2 = w1.trim_matches(|c: char| ! matches!(c, '0'..='9' | '.' | '-'));
let h2 = h1.trim_matches(|c: char| ! matches!(c, '0'..='9' | '.' | '-'));
fn parse_wh(w: Option<&Value>, h: Option<&Value>) -> Option<String> {
let w: &str = w?.trim_matches(|c: char| ! matches!(c, '0'..='9' | '.' | '-'));
let h: &str = h?.trim_matches(|c: char| ! matches!(c, '0'..='9' | '.' | '-'));

// If they're both positive, we're good.
if 0.0 < w2.parse::<f32>().ok()? && 0.0 < h2.parse::<f32>().ok()? {
Some(["0 0 ", w2, " ", h2].concat())
if 0.0 < w.parse::<f32>().ok()? && 0.0 < h.parse::<f32>().ok()? {
let mut out = String::with_capacity(5 + w.len() + h.len());
out.push_str("0 0 ");
out.push_str(w);
out.push(' ');
out.push_str(h);
Some(out)
}
else { None }
}
Expand Down Expand Up @@ -462,6 +479,43 @@ fn ranges(src: &[u8]) -> Option<(usize, usize)> {
mod tests {
use super::*;

#[test]
fn test_hiddentrue() {
let mut raw = r#"<div hidden="true"></div>"#.to_owned();
if let Some(pos) = raw.find(r#" hidden="true""#) {
raw.replace_range(pos+7..pos+14, "");
}
assert_eq!(raw, "<div hidden></div>");
}

#[test]
fn test_parse_stem_id() {
for (raw, expected, borrowed) in [
("image.svg", Some("image"), true),
("image name.svg", Some("imagename"), false),
("ImAgE.svg", Some("ImAgE"), true),
("__.svg", None, true),
] {
if let Some(expected) = expected {
let Some(raw2) = parse_stem_id(raw.as_ref()) else {
panic!("BUG: unable to parse stem/id from {raw:?}");
};
assert_eq!(raw2.as_ref(), expected);
assert_eq!(
matches!(raw2, Cow::Borrowed(_)),
borrowed,
"BUG: expected {raw:?} borrow to be {borrowed}",
);
}
else {
assert!(
parse_stem_id(raw.as_ref()).is_none(),
"BUG: shouldn't have parsed stem/id from {raw:?}",
);
}
}
}

#[test]
#[expect(clippy::type_complexity, reason = "It is what it is.")]
fn test_ranges() {
Expand Down
15 changes: 6 additions & 9 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ include!(concat!(env!("OUT_DIR"), "/yesvgmap-extensions.rs"));

/// # Main.
fn main() {
match _main() {
match main__() {
Ok(()) => {},
Err(e @ (SvgError::PrintHelp | SvgError::PrintVersion)) => { println!("{e}"); },
Err(e) => { Msg::error(e.to_string()).die(1); },
Expand All @@ -98,7 +98,7 @@ fn main() {
///
/// Do our work here so we can easily bubble up errors and handle them nice and
/// pretty.
fn _main() -> Result<(), SvgError> {
fn main__() -> Result<(), SvgError> {
// Parse CLI arguments.
let args = argyle::args()
.with_keywords(include!(concat!(env!("OUT_DIR"), "/argyle.rs")));
Expand All @@ -116,12 +116,9 @@ fn _main() -> Result<(), SvgError> {
Argument::Key("--offscreen") => { hide = HideType::Offscreen; },
Argument::Key("-V" | "--version") => return Err(SvgError::PrintVersion),

Argument::KeyWithValue("-l" | "--list", s) => if let Ok(s) = std::fs::read_to_string(s) {
paths = paths.with_paths(s.lines().filter_map(|line| {
let line = line.trim();
if line.is_empty() { Some(line.to_owned()) }
else { None }
}));
Argument::KeyWithValue("-l" | "--list", s) => {
paths.read_paths_from_file(&s)
.map_err(|_| SvgError::Read(PathBuf::from(s)))?;
},
Argument::KeyWithValue("--map-class", s) => { class.replace(s); },
Argument::KeyWithValue("--map-id", s) => { id.replace(s); },
Expand All @@ -146,7 +143,7 @@ fn _main() -> Result<(), SvgError> {
class.as_deref(),
hide,
&prefix,
paths.into_vec_filtered(|p| Some(E_SVG) == Extension::try_from3(p))
&paths.into_vec_filtered(|p| Some(E_SVG) == Extension::try_from3(p))
)?;

// Save it to a file.
Expand Down

0 comments on commit 95a6345

Please sign in to comment.