Skip to content

fix: warn on CRLF-inflated segment count for every line-break style - #74

Merged
bermudezmt merged 4 commits into
mainfrom
fix/DEVED-14257-conditional-crlf-warning
Oct 26, 2026
Merged

bermudezmt merged 4 commits into
mainfrom
fix/DEVED-14257-conditional-crlf-warning

Conversation

@bermudezmt

@bermudezmt bermudezmt commented Sep 10, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Warn when a message's line-break style costs more SMS segments than the alternative would (CRLF counts as two characters per line break, LF as one). Covers all three line-break states: LF-only, CRLF-only, and mixed.

The check lives in SegmentedMessage._checkForWarnings() in the core library, so the warning is consistent for both the browser UI and any direct consumer of the npm package.

What changed

  • src/libs/SegmentedMessage.ts: _checkForWarnings() covers all three lineBreakStyle states (LF, CRLF, LF+CRLF), warning whenever the message's actual segment count exceeds what the cheaper line-break style would need. Added a small _segmentsCountFor() helper to compute a variant's segment count without re-running the full constructor.
  • src/browser/segmenter.ts: passes segmentedMessage.warnings straight through.
  • _checkForWarnings() still works when called with no argument, since it's emitted in the public .d.ts and previously took no arguments.
  • Rebuilt dist/ and docs/scripts/ per this repo's convention.

Automated testing

  • npm run check - 678/678 tests pass, lint clean.
  • Verified all lineBreakStyle combinations (none, LF, CRLF, mixed) against dist/, both under and over the segment boundary - warnings fire exactly when the alternative line-break style would cost more segments.
  • Verified _checkForWarnings() still works with zero arguments (back-compat check).

Manual testing

Run:

npm start

Paste this exact four-line message into the calculator:

Ce weekend c'est Big Kiff ! Découvrez vite 4 nouveaux menus à partager:
l.dominos.fr/MqGKjT0Vi2
Conditions sur le site Domino's.
STOP : l.dominos.fr/oIv05Yymdm

Expected SMS result:

  • Segments: 1
  • Warning: LF segment count: 1; CRLF may use 2 and affect pricing.

Then test a non-boundary case:

First line
Second line

Expected: 1 segment, no warning.

Also test text with no line breaks at all - expected: 1 segment, no warning.

Note: pasting into the textarea normalizes any \r\n to \n, so this exercises the lineBreakStyle === 'LF' warning path. The already-CRLF/mixed-line-break path can't be triggered through the browser textarea (browsers strip \r from textarea values) - it's covered instead by the SegmentedMessage-level tests in tests/index.test.js.

Fixes #72.

The prior fix only checked lineBreakStyle === 'LF', so messages that
already contain real CRLF or a mix of CRLF/LF got no warning at all,
even when the CRLF encoding was already costing extra segments.

Move the check into SegmentedMessage._checkForWarnings() so it covers
all three line-break styles and is available to every consumer of the
library, not just the browser UI. Revert src/browser/segmenter.ts to
its previous plain pass-through of segmentedMessage.warnings.
_checkForWarnings() is prefixed with an underscore and documented
@Private, but TypeScript still emits it in the public .d.ts, and it
previously took no arguments. Making the message argument required
would break any direct caller (TS compile error, JS runtime crash on
message.replace(...) with message undefined).

Make the parameter optional and fall back to the original generic
line-break warning when omitted, so the previous zero-argument shape
keeps working exactly as before.
@gverni

gverni commented Sep 18, 2026

Copy link
Copy Markdown

Thanks @bermudezmt for your work on this! I tested the PR locally and it works very well with the edge cases I tested.

Few comments on my my side:

  • Since we are working on the warning message, I was thinking it may make more sense to move it up, just below the segment counter, so users can see it more easily.
  • I believe we can improve the logic: this PR is running a full segment calculation (on the message with modified line breaks) at initialization phase. This means that the code is effectively running the segment calculation twice, which is not really needed. In fact it's less expensive and more straightforward to simply calculate the number of line breaks in the message and use that to calculate the total length of the message with the two different types of line break.

Having said that, I think that before merging this we should look at this changes more holistically. The warning for the linke breaks was added inside the library (and hence the npm package) but it's mainly used by the front end: I don't see users of the npm package using it, since it's using an undocumented property of the SegmentedMessage and a private method.

I believe we should decide whether the warning code really lives in the npm package or not. If it does, we should properly document it and possibly surface in a better way in the response. I personally believe it shouldn't be in the npm package, since the initial approach of this tool was to have it running in the same system that calls the Messaging API, so the calculation of the segments and the cost would always be accurate. What do you think?

Per review feedback: revert SegmentedMessage.ts to its 1.3.0 state
(no message parameter, no _segmentsCountFor, no new branches) so the
npm library is untouched. The richer CRLF-vs-LF pricing comparison now
lives entirely in src/browser/segmenter.ts, computed from the line
break count and character total instead of building a second
SegmentedMessage instance.

Also move the warning banner above the segment tape so it's visible
without expanding the "Encoding details" panel.
@bermudezmt

bermudezmt commented Sep 21, 2026 •

Copy link
Copy Markdown
Collaborator Author

Thanks for the detailed feedback, and for the context on how this library is meant to be used, that changes things here.

Addressed:

  • Reverted SegmentedMessage.ts to exactly its 1.3.0 state, no message parameter, no new branches, no library API changes at all.
  • Replaced the second SegmentedMessage construction with the cheap arithmetic you suggested: count line breaks, derive the character total, compare against the segment boundary. No re-segmentation.
  • Moved the warning banner above the segment tape, visible without expanding "Encoding details."
  • @gverni below is a screenshot of the warning banner in its new position, now showing right below the segment stats and above the segment tape, no need to expand "Encoding details" to see it.
crlf-warning-placement

On whether this belongs in the npm package at all: agreed it doesn't. The new CRLF-vs-LF pricing check now lives entirely in segmenter.ts (browser layer only), and the pre-existing warnings/_checkForWarnings() in the library is untouched.

I'll leave that pre-existing one for a separate conversation, since deprecating/removing a field that's been in the public .d.ts since 2022 is a bigger, versioning-adjacent decision I don't want to fold into this PR.

@gverni

gverni commented Oct 19, 2026

Copy link
Copy Markdown

@bermudezmt sorry for the delay in reviewing this.

This looks great! With this code, a warning will be shown every time the message contains a line return:

CleanShot 2026-10-19 at 17 25 53@2x

The LF segment count: X; CRLF may use X and affect pricing. only if a different encoding can cause a higher number of segments.

One thing before merging: please use a chore: prefix for the squash-merge commit title, not fix:.

Why: this repo publishes to npm via semantic-release on every push to main. The library (src/libs) is untouched now, so this change only affects the browser UI, which npm consumers don't use. A fix: title would trigger a patch release that publishes a package with no library changes. (dist/browser/segmenter.js changes, and dist/** is in the published files.)

The docs/ site deploys from the committed files, so the fix still goes live without an npm release. Please also make sure the squash commit message body doesn't contain fix: or BREAKING CHANGE, so it can't be read as a releasable change.

@gverni gverni self-assigned this Oct 20, 2026
@gverni
gverni self-requested a review October 20, 2026 09:42

@gverni gverni left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bermudezmt
bermudezmt merged commit 3c9e75c into main Oct 26, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows CRLF

2 participants