saropa_dart_utils 1.0.6
saropa_dart_utils: ^1.0.6 copied to clipboard
280+ extension methods and utilities for Flutter/Dart. Null-safe string, DateTime, List, Map, and number operations that eliminate boilerplate.
Changelog #
....
-+shdmNMMMMNmdhs+-
-odMMMNyo/-..``.++:+o+/-
/dMMMMMM/ `````
dMMMMMMMMNdhhhdddmmmNmmddhs+-
/MMMMMMMMMMMMMMMMMMMMMMMMMMMMMNh/
. :sdmNNNNMMMMMNNNMMMMMMMMMMMMMMMMm+
o ..~~~::~+==+~:/+sdNMMMMMMMMMMMo
m .+NMMMMMMMMMN
m+ :MMMMMMMMMm
/N: :MMMMMMMMM/
oNs. +NMMMMMMMMo
:dNy/. ./smMMMMMMMMm:
/dMNmhyso+++oosydNNMMMMMMMMMd/
.odMMMMMMMMMMMMMMMMMMMMdo-
-+shdNNMMMMNNdhs+-
``
Made by Saropa. All rights reserved.
Learn more at https://saropa.com, or mailto://dev.tools@saropa.com
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
1.0.6 - 2026-02-19 #
Fixed (32 bugs resolved — full audit) #
Critical / Logic Errors
getUtcTimeFromLocal: was adding offset instead of subtracting; usedfloor()instead oftruncate()for negative fractional offsets (e.g. UTC-5:30). Return type narrowed fromDateTime?toDateTime(never null).isDateAfterToday: was an instance method that ignoredthisentirely, only checking thedateToCheckparameter. Removed the parameter — now correctly checks the receiver against today. Added injectable{DateTime? now}for testability.randomElement: was usingDateTime.now().microsecondsSinceEpoch % length(deterministic, biased). Now uses a module-levelRandominstance withnextInt().isBetween: inclusive mode was using==instead ofisAtSameMomentAsfor boundary equality — boundary values were excluded.removeStart: case-insensitive path was callingnullIfEmpty()on the trimmed match, returningnullinstead of the original string on non-match.last(): was using rune-based indexing, splitting multi-codepoint emoji. Now usescharacterspackage grapheme clusters. Also optimised: replacestoList()+sublist()withchars.skip()to avoid full list allocation.toDateInYear: was crashing withArgumentErrorfor Feb 29 → non-leap year. Now returnsnull.cleanJsonResponse: was unescaping\"before detecting outer quotes, corrupting strings like"hello \"world\"". Now detects outer quotes first.
Medium
betweenResult:endOptionalparameter was declared but never consulted — end-not-found always returnednull. Now correctly returns the tail whenendOptional: trueis passed. Default changed tofalseto preserve backward compatibility.isSameDateOrAfter/isSameDateOrBefore: replaced fragile cascaded year/month/day if-chains with cleantoDateOnly()+!isBefore/!isAfter.isJson('[]'): empty array was returningtruewithoutallowEmpty: true, inconsistent with empty object{}behaviour. Now requiresallowEmpty: truefor both.isJsoncolon check: was checkingvalue.contains(':')(untrimmed) instead oftrimmed.contains(':').formatDouble: no guard for negativedecimalPlaces—toStringAsFixedwould throwRangeError. Now clamps to 0–20.hasDecimals/formatDouble: did not guard againstNaN/Infinity—NaN % 1returnsNaN(not0). Now returnsfalse/'NaN'/'∞'respectively.unescape(HTML): was mapped to regular space (U+0020) instead of non-breaking space (U+00A0). Fixed.unescape(HTML): numeric entity handler allowed surrogate codepoints (U+D800–U+DFFF) which crashjsonEncode. Now rejected with named constants_surrogateMin/_surrogateMax.addHyphens: accepted any 32-char string without validating hex content. Now validates with_hexOnly32Regex.exclude/containsAny: O(n×m) — converted toSetfor O(n) lookup.toFlattenedList: returnednullfor empty outer but[]for all-empty inners. Now returnsnullconsistently for empty results.
Low / Documentation
isYearCurrent: hardcodedDateTime.now()made it untestable. Converted from getter to method with{DateTime? now}injectable parameter.isDateAfterToday/isTodayetc.: same injectablenowpattern applied for testability.weekOfYear: added warning in docs that value can be 0 or 53 at year boundaries; recommendweekNumber()for ISO 8601 compliance.isMidnight: now checks all time components including milliseconds and microseconds.leastOccurrences: corrected copy-paste doc comment that said "highest" instead of "lowest".formatPrecision: hardcodedtoStringAsFixed(2)whole-number check now uses the actualprecisionparameter.betweenResult: improved doc to explain intentionallastIndexOf("outermost match") design.between: documented special case where emptyendreturns the tail fromstart.takeSafe(0): documented thatcount == 0returns the original list (unliketake(0)).weekOfYear/weekNumber(): documented ISO 8601 edge cases at year boundaries.num.length(): documented scientific notation behaviour for values ≥ 1e21.pluralize: removedlength == 1guard that incorrectly skipped single-character strings.forceBetween: corrected misleading dartdoc ("NOT greater than" → correctly describes clamping).truncateWithEllipsisPreserveWords: fixed grapheme-unsafe fallback that could split multi-codepoint emoji; now usescharacters.take()for the search window.toMapStringDynamic: documented silent key collision behaviour whenensureUniqueKey: false.timeToEmoji: boundary was>instead of>=— 7:00am showed moon emoji instead of sun.
Tests #
- 3,022 tests passing (added ~40 new tests covering all fixed bugs)
- Fixed 8 pre-existing tests with incorrect expectations or wrong test names
- Removed duplicate test cases in
date_time_range_utils_test.dart
[1.0.6] - 2026-01-21 #
Changed #
- Extracted magic numbers into named constants across codebase for improved code clarity and linting compliance
- Added 50+ descriptive constants with documentation to date/time, numeric, string, HTML, and UUID utilities
- Migrated date/time validation constants to public exports in
date_constants.dartfor cross-module reuse - Files updated:
datetime/date_constants.dart- Added 15 date/time validation constantsdatetime/date_time_range_utils.dart- Uses shared month constantsdatetime/date_time_utils.dart- Uses shared date/time constantsdatetime/time_emoji_utils.dart- Uses day/night hour constantsdouble/double_extensions.dart- Added percentage and base-10 constantshex/hex_utils.dart- Added hex radix and max length constantshtml/html_utils.dart- Added hex radix and Unicode limit constantsint/int_extensions.dart- Added base-10 constantint/int_string_extensions.dart- Added ordinal number constantsint/int_utils.dart- Added recursion depth constantstring/string_search_extensions.dart- Added ASCII code constantsstring/string_utils.dart- Added alphabet position constantsuuid/uuid_utils.dart- Added UUID format constants
- Resolved
no_magic_numberlinting violations in production code
Fixed #
DateTimeUtils.tomorrow(): Removed nullable type fromminuteandsecondparameters to fixavoid_nullable_parameters_with_default_valueslint warnings
1.0.5 - 2026-01-08 #
Changed #
- Rewrote README with compelling production-proven messaging
- Added before/after code comparison table
- Added real-world use cases section
- Improved About section with library origin story
1.0.0 - 2026-01-07 #
Changed #
- Migrated from GPL v3 to MIT license for broader adoption
- Upgraded saropa_lints from
recommendedtoinsanitytier (all 500+ rules enabled)
Added #
- Pub points badge (dynamic from pub.dev)
- Methods count badge (480+ methods)
- Coverage badge (100%)
- Organized badge assets into
assets/badges/folder
0.5.12 - 2026-01-05 #
Changed #
- Replaced manually flattened lint rules with
saropa_lints: ^1.1.12 - Added
custom_lint: ^0.8.0for custom lint rule support - Configured
recommendedtier (~150 rules) - Simplified
analysis_options.yamlfrom 255 lines to 69 lines - Removed manually flattened flutter_lints/recommended/core rules
0.5.11 #
Added #
Base64Utils- Text compression and decompression (compressText,decompressText)UuidUtils- UUID validation and manipulation (isUUID,addHyphens,removeHyphens)HtmlUtils- HTML text processing (unescape,removeHtmlTags,toPlainText)DoubleExtensions- Double formatting (hasDecimals,toPercentage,formatDouble,forceBetween,toPrecision,formatPrecision)- 103 test cases covering all new utilities
0.5.10 - 2025-12-11 #
Added #
-Versionparameter for CI/CD automation in publish script-Branchparameter to specify target branch- Pre-publish validation step (
flutter pub publish --dry-run) flutter analyzestep before publishing- Working tree status check with user confirmation
- Remote sync check to prevent publishing when behind remote
- Early CHANGELOG version validation
Fixed #
- Step numbering in publish script (was skipping from 4 to 6)
ErrorActionPreferenceissue with try/catch for GitHub release check
Changed #
- Dynamic package name and repo URL extraction from pubspec.yaml and git remote
- Excluded example folder from parent analysis
0.5.9 - 2025-11-25 #
Added #
isJson:allowEmptyparameter to optionally treat{}as valid JSON- 16 test cases for
JsonUtils.isJson
Changed #
substringSafe: Now usescharacters.getRange()for proper UTF-16/emoji supporttruncateWithEllipsis: Uses grapheme cluster length for accurate emoji handlingtruncateWithEllipsisPreserveWords: Uses grapheme cluster lengthlastChars: Uses grapheme cluster length- Breaking: Indices now refer to grapheme clusters, not code units
Fixed #
MakeListExtensions: Changed extension fromTtoT?for nullable typesgetUtcTimeFromLocal: Fixed incorrect documentationgetNthWeekdayOfMonthInYear: Removed stale parameter references from docs
Removed #
UniqueListExtensionsUniqueBy: Removed unusedpropertyComparergeneric parameter
0.5.8 - 2025-11-25 #
Changed #
publish_pub_dev.ps1: Added idempotent handling for git tagspublish_pub_dev.ps1: Added idempotent handling for GitHub releases- Prevents script failures when re-running after partial completion
0.5.7 - 2025-11-25 #
Fixed #
extractCurlyBraces: Switched to non-greedy matching for correct extraction orderremoveSingleCharacterWords: Made Unicode-aware for single-letter words beyond ASCIIreplaceLineBreaks: Improved deduplication for arbitrary replacement stringsgrammarArticle: Enhanced heuristics for silent 'h', "you"-sound words, andone-prefixespossess: Trims input before applying trailing 's' rules
Changed #
repeat: Optimized concatenation withStringBufferlettersOnly/lowerCaseLettersOnly: Simplified to regex-based ASCII filters
0.5.6 #
Added #
UrlExtensions.isSecure- Check if URI uses HTTPS schemeUrlExtensions.addQueryParameter- Add or update query parametersUrlExtensions.hasQueryParameter- Check if query parameter existsUrlExtensions.getQueryParameter- Get query parameter valueUrlExtensions.replaceHost- Create URI with different host
0.5.5 - 2025-11-25 #
Added #
JsonUtils- JSON parsing, type conversion, and validationMapExtensions- Map manipulation utilitiesUrlExtensions- URI manipulation (removeQuery,fileName,isValidUrl,isValidHttpUrl,tryParse)StringBetweenExtensions- Content extraction (between,betweenLast,removeBetween, etc.)StringCharacterExtensions- Character operations (splitByCharacterCount,charAtOrNull)StringSearchExtensions- Search utilities (containsAnyIgnoreCase,indexOfAll,lastIndexOfPattern)MonthUtils,WeekdayUtils,SerialDateUtils- Date constant lookups- DateTime extensions:
mostRecentSunday,mostRecentWeekday,dayOfYear,weekOfYear,numOfWeeks,weekNumber,toSerialString,toSerialStringDay - String extensions:
removeSingleCharacterWords,removeLeadingAndTrailing,firstWord,secondWord,endsWithAny,endsWithPunctuation,isAny,extractCurlyBraces,obscureText,hasInvalidUnicode,isVowel,hasAnyDigits - Iterable/Num extensions:
randomElement,containsAll,toDoubleOrNull,toIntOrNull DateTimeUtils.isValidDateParts- Comprehensive date part validationconvertDaysToYearsAndMonths-includeRemainingDaysoption- 2850 tests (all passing)
0.5.4 #
Fixed #
isBetweenRange: Properly forwardsinclusiveparameterisAnnualDateInRange: Correctly handles date ranges spanning year boundariesisNthDayOfMonthInRange: Cross-year range validationinRangeandisNowInRange: Default to inclusive boundary semanticsequalsIgnoringOrder: Correctly compares duplicate countshexToInt: Case-sensitive overflow checktoUpperLatinOnly: O(n²) → O(n) using StringBufferupperCaseLettersOnly: O(n²) → O(n) using StringBuffertruncateWithEllipsisPreserveWords: Returns truncated content when first word exceeds cutoffcontainsIgnoreCase: Empty string is contained in any stringconvertDaysToYearsAndMonths: Improved precision using average days
Added #
- 110 new test cases for algorithm fixes
0.5.3 - 2025-11-12 #
Changed #
- Enhanced
string_utils.dartto optimize final regex usages - Improved documentation for
CommonRandomand list generation
0.5.1 - 2025-08-19 #
0.5.0 - 2025-08-19 #
0.4.4 - 2025-08-18 #
0.4.3 - 2025-02-24 #
0.3.18 - 2025-01-07 #
0.3.13 #
Added #
- Unused flutter code detection script
- TED talks video library to Code of Conduct
Changed #
- H.O.N.E.S.T.I. acronym wording in Code of Conduct
- Code of Conduct with Saropa logo, examples, survey, and exercise
- Link to Code of Conduct in README.md
- Renamed
docfolder todocs
Removed #
- Codecov integration
0.2.3 #
0.2.0 #
0.1.0 #
0.0.11 #
Added #
DateConstants.unixEpochDateDateConstantExtensions.isUnixEpochDateDateConstantExtensions.isUnixEpochDateTimeIntStringExtensions.ordinalStringUtils.getNthLatinLetterLowerStringUtils.getNthLatinLetterUpperIntUtils.findGreatestCommonDenominatorIntExtensions.countDigits
Fixed #
StringExtensions.removeStartreturns input when search param is empty
Removed #
- Deprecated functions in
StringNullableExtensions
0.0.5 #
Added #
- Documentation for all methods
- Code usage in Example App
- Code usage in README.md
- String extension methods